当前位置: 首页 > 知识库问答 >
问题:

每行具有不同的JCombobox的JTable

勾裕
2023-03-14

我有一个在运行时加载行的表。加载后,用户需要在每一行的第一列中从JComboBox中选择一个项目。然后他需要在每行的同一行上从另一个JComboBox中选择一个项目。第二个JComboBox的内容取决于第一个JComboBox的选择。

我现在的编码方式是更改整个第二列的combobox内容。

columnProfile.setCellEditor(new DefaultCellEditor(comboBoxProf))

有没有一种方法可以让每一行的组合框对象都不一样,这样我就可以在第一个组合框中选择一个值的时候处理它?

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;


import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;


public class TableRenderDemo extends JPanel {
    private boolean DEBUG = false;
    JComboBox comboBox2;
    JComboBox comboBox1;
    public TableRenderDemo() {
        super(new GridLayout(1,0));

        JTable table = new JTable(new MyTableModel());
        table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        table.setFillsViewportHeight(true);
        JScrollPane scrollPane = new JScrollPane(table);
        initColumnSizes(table);

        setUpSportColumn(table, table.getColumnModel().getColumn(2));
        setUpYearsColumn(table, table.getColumnModel().getColumn(3));

        add(scrollPane);
        table.getModel().addTableModelListener(new TableModelListener() {

            public void tableChanged(TableModelEvent e) {

                if (e.getColumn() == 2){
                    comboBox2.removeAllItems();
                    /*REFILL COMBOBOX WITH WHAT I NEED FOR THIS ROW ONLY*/
                }


            }
                  }); 
    }

    private void initColumnSizes(JTable table) {
        MyTableModel model = (MyTableModel)table.getModel();
        TableColumn column = null;
        Component comp = null;
        int headerWidth = 0;
        int cellWidth = 0;
        Object[] longValues = model.longValues;
        TableCellRenderer headerRenderer =
            table.getTableHeader().getDefaultRenderer();

        for (int i = 0; i < 5; i++) {
            column = table.getColumnModel().getColumn(i);

            comp = headerRenderer.getTableCellRendererComponent(
                                 null, column.getHeaderValue(),
                                 false, false, 0, 0);
            headerWidth = comp.getPreferredSize().width;

            comp = table.getDefaultRenderer(model.getColumnClass(i)).
                             getTableCellRendererComponent(
                                 table, longValues[i],
                                 false, false, 0, i);
            cellWidth = comp.getPreferredSize().width;

            if (DEBUG) {
                System.out.println("Initializing width of column "
                                   + i + ". "
                                   + "headerWidth = " + headerWidth
                                   + "; cellWidth = " + cellWidth);
            }

            column.setPreferredWidth(Math.max(headerWidth, cellWidth));
        }
    }

    public void setUpSportColumn(JTable table,
                                 TableColumn sportColumn) {
        //Set up the editor for the sport cells.
        comboBox1 = new JComboBox();
        comboBox1.addItem("Snowboarding");
        comboBox1.addItem("Rowing");
        comboBox1.addItem("Knitting");
        comboBox1.addItem("Speed reading");
        comboBox1.addItem("Pool");
        comboBox1.addItem("None of the above");
        sportColumn.setCellEditor(new DefaultCellEditor(comboBox1));


        DefaultTableCellRenderer renderer =
                new DefaultTableCellRenderer();
        renderer.setToolTipText("Click for combo box");
        sportColumn.setCellRenderer(renderer);
    }
    public void setUpYearsColumn(JTable table,
            TableColumn yearColumn) {

comboBox2 = new JComboBox();
comboBox2.addItem("1");
comboBox2.addItem("2");
comboBox2.addItem("3");
comboBox2.addItem("4");
comboBox2.addItem("5");
comboBox2.addItem("6");
yearColumn.setCellEditor(new DefaultCellEditor(comboBox2));

//Set up tool tips for the sport cells.
DefaultTableCellRenderer renderer =
new DefaultTableCellRenderer();
renderer.setToolTipText("Click for combo box");
yearColumn.setCellRenderer(renderer);
}

    class MyTableModel extends AbstractTableModel {
        private String[] columnNames = {"First Name",
                                        "Last Name",
                                        "Sport",
                                        "# of Years",
                                        "Vegetarian"};
        private Object[][] data = {
        {"Kathy", "Smith",
         "Snowboarding", "1", new Boolean(false)},
        {"John", "Doe",
         "Rowing", "1", new Boolean(true)},
        {"Sue", "Black",
         "Knitting", "1", new Boolean(false)},
        {"Jane", "White",
         "Speed reading", "1", new Boolean(true)},
        {"Joe", "Brown",
         "Pool", "1", new Boolean(false)}
        };

        public final Object[] longValues = {"Jane", "Kathy",
                                            "None of the above",
                                            new Integer(20), Boolean.TRUE};

        public int getColumnCount() {
            return columnNames.length;
        }

        public int getRowCount() {
            return data.length;
        }

        public String getColumnName(int col) {
            return columnNames[col];
        }

        public Object getValueAt(int row, int col) {
            return data[row][col];
        }


        public Class getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }


        public boolean isCellEditable(int row, int col) {

            if (col < 2) {
                return false;
            } else {
                return true;
            }
        }


        public void setValueAt(Object value, int row, int col) {
            if (DEBUG) {
                System.out.println("Setting value at " + row + "," + col
                                   + " to " + value
                                   + " (an instance of "
                                   + value.getClass() + ")");
            }

            data[row][col] = value;
            fireTableCellUpdated(row, col);

            if (DEBUG) {
                System.out.println("New value of data:");
                printDebugData();
            }
        }

        private void printDebugData() {
            int numRows = getRowCount();
            int numCols = getColumnCount();

            for (int i=0; i < numRows; i++) {
                System.out.print("    row " + i + ":");
                for (int j=0; j < numCols; j++) {
                    System.out.print("  " + data[i][j]);
                }
                System.out.println();
            }
            System.out.println("--------------------------");
        }
    }


    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("TableRenderDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


        TableRenderDemo newContentPane = new TableRenderDemo();
        newContentPane.setOpaque(true); 
        frame.setContentPane(newContentPane);

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {

        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

共有1个答案

嵇星海
2023-03-14

假设您将数据保存在map 中,其中map的键表示第一个JComboBox保存的值,而map的值表示第二列的JComboBox保存的变化值(数据不需要这样设置,但对于MCVE/演示来说很容易),并将此map称为DataMap,那么列编辑器可能会如下所示:

    column1.setCellEditor(new DefaultCellEditor(combo1) {
        @SuppressWarnings("unchecked")
        @Override
        public Component getTableCellEditorComponent(JTable table, Object value,
                boolean isSelected, int row, int column) {

            // the items that will fill our JComboBox. Initially its empty
            Object[] items = new Object[]{};

            // get the value in the column to the left
            Object column0Value = table.getValueAt(row, column - 1);
            if (column0Value != null) {
                // if the value is not null, then get the map's values
                // and use it to fill our items array
                items = dataMap.get(column0Value).toArray();
            } 

            // get the super component, the JComboBox that is being used
            // as an editor:
            JComboBox<Object> superCombo = (JComboBox<Object>) super.getTableCellEditorComponent(table, value, isSelected,
                    row, column);

            // create a model and fill with items
            DefaultComboBoxModel<Object> comboModel = new DefaultComboBoxModel<>(items);

            // set the cell editor's model and return
            superCombo.setModel(comboModel);
            return superCombo;
        }
    });

例如,请检查此MCVE作为使用上述单元格编辑器的示例,并作为一个MCVE的示例,它将在您将来的问题中很好地工作

import java.awt.Component;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;

@SuppressWarnings("serial")
public class TableWithMultCombos extends JPanel {
    private static final String[] COLUMN_NAMES = { "Day of Week", "Number" };
    private Map<String, List<String>> dataMap = new LinkedHashMap<>();
    private DefaultTableModel tblModel = new DefaultTableModel(COLUMN_NAMES, 5);
    private JTable table = new JTable(tblModel);
    private DefaultComboBoxModel<Object> combo2Model = new DefaultComboBoxModel<>();
    private JComboBox<Object> combo0 = null;
    private JComboBox<Object> combo1 = new JComboBox<>(combo2Model);

    public TableWithMultCombos() {
        dataMap.put("Monday", Arrays.asList(new String[] { "Mon - 1", "Mon - 2", "Mon - 3", "Mon - 4" }));
        dataMap.put("Tuesday", Arrays.asList(new String[] { "Tues - 1", "Tues - 2", "Tues - 3", "Tues - 4" }));
        dataMap.put("Wednesday", Arrays.asList(new String[] { "Wed - 1", "Wed - 2", "Wed - 3", "Wed - 4" }));
        dataMap.put("Thursday", Arrays.asList(new String[] { "Thurs - 1", "Thurs - 2", "Thurs - 3", "Thurs - 4" }));
        dataMap.put("Friday", Arrays.asList(new String[] { "Fri - 1", "Fri - 2", "Fri - 3", "Fri - 4" }));
        combo0 = new JComboBox<>(dataMap.keySet().toArray());

        TableColumn column0 = table.getColumnModel().getColumn(0);
        column0.setCellEditor(new DefaultCellEditor(combo0));

        TableColumn column1 = table.getColumnModel().getColumn(1);
        column1.setCellEditor(new DefaultCellEditor(combo1) {
            @SuppressWarnings("unchecked")
            @Override
            public Component getTableCellEditorComponent(JTable table, Object value,
                    boolean isSelected, int row, int column) {

                // the items that will fill our JComboBox. Initially its empty
                Object[] items = new Object[]{};

                // get the value in the column to the left
                Object column0Value = table.getValueAt(row, column - 1);
                if (column0Value != null) {
                    // if the value is not null, then get the map's values
                    // and use it to fill our items array
                    items = dataMap.get(column0Value).toArray();
                } 

                // get the super component, the JComboBox that is being used
                // as an editor:
                JComboBox<Object> superCombo = (JComboBox<Object>) super.getTableCellEditorComponent(table, value, isSelected,
                        row, column);

                // create a model and fill with items
                DefaultComboBoxModel<Object> comboModel = new DefaultComboBoxModel<>(items);

                // set the cell editor's model and return
                superCombo.setModel(comboModel);
                return superCombo;
            }
        });

        table.setFillsViewportHeight(true);
        add(new JScrollPane(table));
    }

    private static void createAndShowGui() {
        TableWithMultCombos mainPanel = new TableWithMultCombos();

        JFrame frame = new JFrame("TableWithMultCombos");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}
 类似资料:
  • 我创建了包含员工信息的。在这个JTable中,我添加了名为“资历”的列。此列由表示(每行的内容不同)。例如: 内容取自。 问题是在第1行和第2行中选择的项目是“程序员”,但是“程序员”不应该出现在第2行中。只有当我单击时,才会出现正确的列表,即第2行-{“writer”,“editor”}。

  • 我正在尝试使用GridLayoutManager构建一个RecyclerView,它每行有一个可变的列计数,如下所示: 同一行中所有项目的宽度之和将始终为屏幕宽度。 我试图重新组织项目列表,按行列表分组,然后每行膨胀一个线性布局。它不太好。 所以我被困住了,没有任何想法。任何帮助都将非常感激

  • 我想在我的应用程序中创建一个JTable。该表将包含两个库,第一个是软件模块的名称。第二列需要包含一个JComboBox,第一列中包含软件模块的修订号。 这甚至可能,或者我需要找到另一种方法来做到这一点?(例如:将按钮放在单元格中,然后从弹出窗口中选择修订版本) 提前谢谢你!

  • 问题内容: 我试图用来创建我的,以确保我的构建/项目的质量。该项目也需要使用和。一切在我的本地计算机上都可以正常运行,但是现在我正在尝试使环境一致,可重现。当我尝试在新的虚拟机中运行时,会中断一个在本机中正常运行但 不在 新vm中运行的。 我检查了版本,,,(其)一切都是一样的。但是,我的Maven项目在此测试中失败了。 我在这里想念什么?任何想法,建议都会受到赞赏,因为我现在还没有想法,到目前为

  • 问题内容: 使用Pandas或CSV模块将每行具有不同列数的CSV导入Pandas DataFrame的最佳方法是什么。 使用此代码: 产生以下错误 问题答案: 在read_csv()中提供列名列表应该可以解决问题。 例如:names = [‘a’,’b’,’c’,’d’,’e’] https://github.com/pydata/pandas/issues/2981 编辑:如果您不想提供列名,

  • 问题内容: 我遇到的情况是可以从多个不同的域访问应用程序。例如, foo.com 和 bar.com 在理论上都可以指向我的应用程序。此外,它们的子域也可以指向我的应用程序,例如 red.foo.com 和 blue.foo.com 。我正在使用Express cookie会话,该会话的初始化代码如下所示: 当用户访问 foo.com 或其任何子域时,这种方法效果很好,但是 bar.com 无法正