代码之家  ›  专栏  ›  技术社区  ›  Mr. Wallet

在JTable中,编辑单元格唯一的JComboBoxes时更新显示的项目

  •  0
  • Mr. Wallet  · 技术社区  · 11 年前

    我有一个GUI,其中有一列JComboBoxes,其中每一个都是唯一的。我真的不明白我在做什么,所以在一系列超长的障碍中,最新的一个是,当编辑一个框时,它不会显示新选择的值。如果再次选中该框,则单元格中的值将更新为以前选择的值,因此可能只是表/渲染器不更新的问题。

    我怀疑我可能需要在某个地方为每个组合框注册一个监听器,但我不知道在哪个类上注册哪种类型的监听器。

    以下是SSCCE,尽我所能简明扼要地说明了目前的设计:

    import java.awt.Component;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    import javax.swing.DefaultCellEditor;
    import javax.swing.JComboBox;
    import javax.swing.JFrame;
    import javax.swing.JTable;
    import javax.swing.border.EmptyBorder;
    import javax.swing.event.TableModelListener;
    import javax.swing.table.TableCellEditor;
    import javax.swing.table.TableCellRenderer;
    import javax.swing.table.TableColumn;
    import javax.swing.table.TableModel;
    
    @SuppressWarnings("serial")
    public class ComboBoxTableGUI extends JFrame {
    
        public List<SampleCollection> masterList;
    
        public static void main(String[] args) {
            new ComboBoxTableGUI();
        }
    
        public ComboBoxTableGUI() {
            // create a collection of 10 collections, each with 1-10 Strings
            masterList = new ArrayList<SampleCollection>();
            Random rnd = new Random();
            for (int i = 0; i < 10; i++) {
                SampleCollection sc = new SampleCollection("Option " + i + ":");
                int choices = rnd.nextInt(9) + 1;
                for (int j = 0; j < choices; j++) {
                    sc.choices.add("Choice " + j);
                }
                sc.selectedChoice = sc.choices.get(0);
                masterList.add(sc);
            }
    
            this.setSize(500, 500);
            this.setLocationRelativeTo(null);
    
            TableModel optionTableModel = new OptionTableModel();
            JTableWithCustomEditors optionsTable = new JTableWithCustomEditors(optionTableModel);
    
            this.add(optionsTable);
    
            TableColumn optionCol = optionsTable.getColumnModel().getColumn(1);
            optionCol.setCellRenderer(new CustomComboBoxRenderer());
    
            List<TableCellEditor> editors = new ArrayList<TableCellEditor>();
            for (SampleCollection collection : masterList) {
                JComboBox<String> cb = new JComboBox<String>();
                for (String choice : collection.choices) {
                    cb.addItem(choice);
                }
                DefaultCellEditor editor = new DefaultCellEditor(cb);
                editors.add(editor);
            }
            optionsTable.editors = editors;
    
            this.setVisible(true);
        }
    
        public class SampleCollection {
            public String name, selectedChoice;
            public List<String> choices;
    
            public SampleCollection(String name) {
                this.name = name;
                this.choices = new ArrayList<String>();
            }
        }
    
        public class JTableWithCustomEditors extends JTable {
            public List<TableCellEditor> editors;
    
            public JTableWithCustomEditors(TableModel model) {
                super(model); // lol
            }
    
            @Override
            public TableCellEditor getCellEditor(int row, int column) {
                if (column == 1)
                    return editors.get(row);
                else
                    return super.getCellEditor(row, column);
            }
        }
    
        class CustomComboBoxRenderer extends JComboBox<String> implements
                TableCellRenderer {
            public CustomComboBoxRenderer() {
                setBorder(new EmptyBorder(0, 0, 0, 0));
            }
    
            public Component getTableCellRendererComponent(JTable table,
                    Object value, boolean isSelected, boolean hasFocus, int row,
                    int column) {
    
                removeAllItems();
                addItem(((SampleCollection) value).selectedChoice);
    
                this.setSelectedIndex(0);
                return this;
            }
        }
    
        public class OptionTableModel implements TableModel {
            private List<TableModelListener> listeners;
    
            public OptionTableModel() {
                listeners = new ArrayList<TableModelListener>();
            }
    
            @Override
            public void addTableModelListener(TableModelListener l) {
                listeners.add(l);
            }
    
            @Override
            public Class<?> getColumnClass(int columnIndex) {
                if (columnIndex == 1)
                    return SampleCollection.class;
                else
                    return String.class;
            }
    
            @Override
            public int getColumnCount() {
                return 2;
            }
    
            @Override
            public String getColumnName(int columnIndex) {
                if (columnIndex == 0)
                    return "Name";
                else
                    return "Selection";
            }
    
            @Override
            public int getRowCount() {
                if (masterList == null)
                    return 0;
                else
                    return masterList.size();
            }
    
            @Override
            public Object getValueAt(int rowIndex, int columnIndex) {
                if (columnIndex == 0)
                    return masterList.get(rowIndex).name;
                else
                    return masterList.get(rowIndex);// also tried .choices
            }
    
            @Override
            public boolean isCellEditable(int rowIndex, int columnIndex) {
                if (columnIndex == 1)
                    return true;
                else
                    return false;
            }
    
            @Override
            public void removeTableModelListener(TableModelListener l) {
                listeners.remove(l);
            }
    
            @Override
            public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
                // the values are grabbed when the user clicks an OK button, right
                // now I just need to get it rendering
            }
        }
    }
    
    1 回复  |  直到 11 年前
        1
  •  1
  •   camickr    11 年前

    您的TableModel实现不正确。

    首先,数据应该存储在模型中,而不是作为类中的实例变量。

    这个 setValueAt(...) 方法应该更新List中的数据,然后应该调用 fireTableCellUpdated(...) 这将告诉表数据已经更改,以便可以重新绘制单元格。