JTable 中 JCombobox 的 setSelectedItem

setSelectedItem of JCombobox in a JTable

我有一个 JTable,我正在向三个不同的列添加三个 JComboBox。 现在我想为我拥有的每一行设置所选项目。问题是,我需要每一行的 ID 才能做到这一点。 所以我尝试了不同的 Listener,最好的结果来自 FocusListener,但是我总是必须先单击该行,然后再单击 JComboBox,这很费力。 这是一个例子:

JTable table = new JTable();
    Vector<ArrayList<Object>> data = new Vector<ArrayList<Object>>();
    for (int i = 0; i < 5; i++)
    {
        ArrayList<Object> object = new ArrayList<Object>();
        object.add(i);
        object.add("name");
        object.add(i+1);
        object.add(i+1);
        object.add(i+1);
        data.add(object);
    }
    DefaultTableModel tableModel = new DefaultTableModel() {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        @Override
        public boolean isCellEditable(int row, int column) {
            if (column < 2)
                return false;
            return true;
        }
    };
    tableModel.setColumnIdentifiers(new String[] {"ID", "Name", "OK", "Other", "Error"});
    tableModel.addTableModelListener(new TableModelListener()
    {

        @Override
        public void tableChanged(TableModelEvent e)
        {
            if (e.getType() == TableModelEvent.UPDATE)
            {
                int row = e.getFirstRow();
                int column = e.getColumn();
                TableModel table_model = (TableModel) e.getSource();
                ArrayList<Object> changed_data = (ArrayList<Object>) table_model.getValueAt(row, column);
                String row_id = String.valueOf(table_model.getValueAt(row, 0));
                for (ArrayList<Object> list : data)
                {
                    String compare_id = String.valueOf(list.get(0));
                    if (row_id.equals(compare_id))
                    {
                        list.set(column, String.valueOf(changed_data.get(0)));
                        for (int i = table_model.getRowCount()-1; i >= 0 ; i--)
                        {
                            tableModel.removeRow(i);
                        }

                        for (ArrayList<Object> object : data)
                        {
                            Vector<String> vector = new Vector<String>();
                            vector.addElement(String.valueOf(object.get(0)));
                            vector.addElement(String.valueOf(object.get(1)));
                            vector.addElement(String.valueOf(object.get(2)));
                            vector.addElement(String.valueOf(object.get(3)));
                            vector.addElement(String.valueOf(object.get(4)));
                            tableModel.addRow(vector);
                        }

                        TableColumn column_ok = table.getColumnModel().getColumn(2);
                        TableColumn column_other = table.getColumnModel().getColumn(3);
                        TableColumn column_error = table.getColumnModel().getColumn(4);

                        JComboBox<ArrayList<Object>> combobox_ok = new JComboBox<ArrayList<Object>>(data);
                        JComboBox<ArrayList<Object>> combobox_other = new JComboBox<ArrayList<Object>>(data);
                        JComboBox<ArrayList<Object>> combobox_error = new JComboBox<ArrayList<Object>>(data);

                        column_ok.setCellEditor(new DefaultCellEditor(combobox_ok));
                        column_other.setCellEditor(new DefaultCellEditor(combobox_other));
                        column_error.setCellEditor(new DefaultCellEditor(combobox_error));
                        break;
                    }
                }
            }
        }
    });
    table.setModel(tableModel);
    for (ArrayList<Object> object : data)
    {
        Vector<String> vector = new Vector<String>();
        vector.addElement(String.valueOf(object.get(0)));
        vector.addElement(String.valueOf(object.get(1)));
        vector.addElement(String.valueOf(object.get(2)));
        vector.addElement(String.valueOf(object.get(3)));
        vector.addElement(String.valueOf(object.get(4)));
        tableModel.addRow(vector);
    }

    TableColumn column_ok = table.getColumnModel().getColumn(2);
    TableColumn column_other = table.getColumnModel().getColumn(3);
    TableColumn column_error = table.getColumnModel().getColumn(4);

    JComboBox<ArrayList<Object>> combobox_ok = new JComboBox<ArrayList<Object>>(data);
    JComboBox<ArrayList<Object>> combobox_other = new JComboBox<ArrayList<Object>>(data);
    JComboBox<ArrayList<Object>> combobox_error = new JComboBox<ArrayList<Object>>(data);

    column_ok.setCellEditor(new DefaultCellEditor(combobox_ok));
    column_other.setCellEditor(new DefaultCellEditor(combobox_other));
    column_error.setCellEditor(new DefaultCellEditor(combobox_error));

    JScrollPane scrollPane = new JScrollPane();
    scrollPane.getViewport().add(table);

    JFrame frame = new JFrame();
    frame.add(scrollPane);
    frame.setSize(400, 200);
    frame.setVisible(true);

现在,在第一行第三列 ("OK") 中,您可以在 JComboBox 中选择代表一行的不同条目。所以一行有三个 JComboBoxes,它们引用另一行。 如果您单击这样的 JComboBox,您会注意到它总是选择第一个条目,而不是您在单击它之前看到的带有编号的条目。

也许你现在明白我想做什么了?

If you click in such a JComboBox, you will notice it always chooses the first entry and not the entry with the number you saw before clicking at it.

针对问题的这一方面,以下简化的完整示例始终在单元格的编辑器处于活动状态时显示所选条目。您可以根据需要替换组合的 default renderer 以显示不同的结果。此外,

  • 覆盖 getPreferredScrollableViewportSize() 以建立所需的 table 大小。

  • 尽可能使用类型参数;根据需要覆盖 getColumnClass(),对于 example.

  • 覆盖 getValueAt(),如图 here and 所示,用于相关数据。

  • 请注意下面 isCellEditable() 的简化实现。

import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.Arrays;
import java.util.Vector;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;

/**
 * @see 
 */
public class TableComboTest {

    private Vector<Vector<String>> createData() {
        Vector<Vector<String>> data = new Vector<Vector<String>>();
        for (int i = 0; i < 5; i++) {
            Vector<String> rowVector = new Vector<String>();
            rowVector.add(String.valueOf(i));
            rowVector.add("name");
            rowVector.add(String.valueOf(i + 1));
            rowVector.add(String.valueOf(i + 1));
            rowVector.add(String.valueOf(i + 1));
            data.add(rowVector);
        }
        return data;
    }

    private void display() {
        Vector<Vector<String>> data = createData();
        Vector<String> names = new Vector<>(Arrays.asList("ID", "Name", "OK", "Other", "Error"));
        DefaultTableModel tableModel = new DefaultTableModel(data, names) {

            @Override
            public boolean isCellEditable(int row, int column) {
                return column > 1;
            }
        };
        JTable table = new JTable(tableModel) {
            @Override
            public Dimension getPreferredScrollableViewportSize() {
                return new Dimension(getPreferredSize().width, getRowHeight() * 4);
            }
        };

        TableColumn column_ok = table.getColumnModel().getColumn(2);
        TableColumn column_other = table.getColumnModel().getColumn(3);
        TableColumn column_error = table.getColumnModel().getColumn(4);

        String[] choices = new String[]{"1", "2", "3", "4", "5"};
        JComboBox<String> combobox_ok = new JComboBox<>(choices);
        JComboBox<String> combobox_other = new JComboBox<String>(choices);
        JComboBox<String> combobox_error = new JComboBox<String>(choices);

        column_ok.setCellEditor(new DefaultCellEditor(combobox_ok));
        column_other.setCellEditor(new DefaultCellEditor(combobox_other));
        column_error.setCellEditor(new DefaultCellEditor(combobox_error));

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JScrollPane(table));
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new TableComboTest()::display);
    }
}