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

标签 java swing jtable jcombobox tablecellrenderer

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

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

这是 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
        }
    }
}

最佳答案

您的 TableModel 实现不正确。

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

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

关于java - 在 JTable 中,编辑单元格唯一的 JComboBox 时更新显示的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19554435/

相关文章:

java - Android:使用按钮编辑文本字段

java - 将 JTabbedpane 拖出到窗口并自动创建新的 JFrame

java - ComboBox 作为 JTable 的 CellRenderer

java - 如何通过动态数组或 ArrayList 使用数据库中的值填充 JTable

Java jtable 允许行选择

java - JTable 显示 Mysql 表中的同一行

java - 具有代码生成功能的开源 UML eclipse 插件

java - 正则表达式精确匹配 n 次出现的字母和 m 次出现的数字

java - 关于排除注释行

java - Swing 中的增量图形