在单元格编辑器中调用操作后,单元格不会更新

发布于 2024-12-27 11:55:37 字数 5016 浏览 2 评论 0原文

我使用带有单元格渲染器的表格,它允许我在每个单元格中放置一个带有值的按钮“x”,以便我可以通过按按钮删除单元格的值。单元格编辑器将操作侦听器分配给按钮,并在按下按钮时调用适当的操作。

作为 DefaultTableModel 的表模型中的每一列都由值的数组列表填充。我成功地通过按下按钮从数组列表中删除了正确的值,并且表中的每个其他单元格在更改后都会刷新,但被删除的值的单元格保持不变。如果我重新启动应用程序或向数组列表添加一个值,表将按预期刷新,并且一切看起来都应有的样子。

那么问题是,单元格渲染器似乎不会忘记单元格的初始值,因此即使重新绘制表格,仍然会继续将该值打印到单元格中。有谁知道我如何正确刷新表格以便正确显示值?

表格类:

public class Table extends JTable {

public static DefaultTableModel model = new DefaultTableModel();
private Days d;
private JFrame frame;
private AddCellRenderer renderer;
private AddCellEditor editor;

public Table(Days d, JFrame frame) {
    // Assign the table model to the table
    super(model);
    this.d = d;
    this.frame = frame;

    // Define dimensions of table
    model.setRowCount(11);
    model.setColumnCount(5);

    // Block resizing and reordering of headers
    this.setColumnSelectionAllowed(false);
    this.setRowSelectionAllowed(false);
    this.setCellSelectionEnabled(true);
    this.setTableHeader(null);

    // Define first row height
    this.setRowHeight(38);
    // Define all other row's heights
    this.setRowHeight(0, 45);

    this.d.setTable(this);

    for (int i = 0; i < 5; i++) {
        editor = new AddCellEditor(new JCheckBox(), d.getVisibleDays().get(i), this);
        renderer = new AddCellRenderer(d.getVisibleDays().get(i), editor);
        this.getColumnModel().getColumn(i).setCellRenderer(renderer);
        this.getColumnModel().getColumn(i).setCellEditor(editor);
    }

    this.refresh();
}

public void refresh() {

    // Empty table
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 11; j++) {
            this.getModel().setValueAt(null, j, i);
        }
    }

    // Populate table with entries for each day
    for (int i = 0; i < 5; i++) {

        Iterator<String> iterator = d.getVisibleDays().get(i).getEntryListIterator();

        int j = 0;

        while(iterator.hasNext()){
            String s = iterator.next();
            this.getModel().setValueAt(s, (j+1), i);
            j++;
        }

        this.getModel().setValueAt(d.getVisibleDays().get(i).getDayName(), 0, i);
    }
}

public void modelClearValueAt(int row, int column) {
    this.getModel().setValueAt(null, row, column);
}
}

单元格编辑器类:

public class AddCellEditor extends DefaultCellEditor {

private JPanel headerPanel;
private JPanel entryPanel;
private JLabel dayName;
private JLabel entryValue;
protected JButton addButton;
private JButton removeButton;
private String label;
private int row;
private int column;
private Day day;
private String date;
private Table table;
private AddCellRenderer renderer;

public AddCellEditor(JCheckBox checkBox, Day day, Table table) {
    super(checkBox);
    this.day = day;
    this.table = table;
    date = day.getDayDate();
    headerPanel = new JPanel();
    headerPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
    entryPanel = new JPanel();
    entryPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
    dayName = new JLabel();
    entryValue = new JLabel();
    addButton = new JButton();
    removeButton = new JButton();
    headerPanel.add(dayName);
    headerPanel.add(addButton);
    entryPanel.add(entryValue);
    entryPanel.add(removeButton);
    addButton.setOpaque(true);
    addButton.setPreferredSize(new Dimension(16, 16));
    removeButton.setOpaque(true);
    removeButton.setPreferredSize(new Dimension(16, 16));
    addButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("Add pressed");
            addItem();
            fireEditingStopped();
        }
    });
    removeButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("Remove pressed");
            removeItem();
            getTable().refresh();
            fireEditingStopped();
        }
    });

}

public void setRenderer(AddCellRenderer renderer) {
    this.renderer = renderer;
}

public Component getTableCellEditorComponent(JTable table, 
        Object value, boolean isSelected, int row, int column) {

    this.row = row;
    this.column = column;

    if (row == 0) {
         return this.headerPanel;
    }
    if (row != 0 && value != null) {
        return this.entryPanel;
    }
    return null;
}

public void addItem() {
    String input = JOptionPane.showInputDialog("Add entry for " + label + ":");

    if ((input != null) && (input.length() > 0)) {
        System.out.println("Added: " + input + "Item");
        day.addEntry(input, column);
    }
}

public void removeItem() {
    table.modelClearValueAt(row, column);
    day.removeEntry(row-1);
    System.out.println("Item removed");
}

public Table getTable() {
    return this.table;
}

public boolean stopCellEditing() {
    return super.stopCellEditing();
}

protected void fireEditingStopped() {
    super.fireEditingStopped();
}
}

提前致谢

I'm using a table with a cell renderer which allows me to place a button "x" in each cell with a value so that i can delete the value of the cell by pressing the button. The cell editor assigns the action listener to the button and the proper actions are called when the button is pressed.

Every column in the table model which is a DefaultTableModel is populated by an array list of values. I successfully manage to delete the right value from the array list by pressing the button and every other cell in the table refreshes after the change but the cell which's value was deleted remains unchanged. If i restart the application or add a value to the array list the table refreshes as expected and everything looks as it should.

Mo problem then is that is seems like the cell renderer won't forget the initial value of the cell and therefore still continues to print this value into the cell even though the table is redrawn. Does anyone have an idea of how i could properly refresh the table so the values are correctly shown?

Table class:

public class Table extends JTable {

public static DefaultTableModel model = new DefaultTableModel();
private Days d;
private JFrame frame;
private AddCellRenderer renderer;
private AddCellEditor editor;

public Table(Days d, JFrame frame) {
    // Assign the table model to the table
    super(model);
    this.d = d;
    this.frame = frame;

    // Define dimensions of table
    model.setRowCount(11);
    model.setColumnCount(5);

    // Block resizing and reordering of headers
    this.setColumnSelectionAllowed(false);
    this.setRowSelectionAllowed(false);
    this.setCellSelectionEnabled(true);
    this.setTableHeader(null);

    // Define first row height
    this.setRowHeight(38);
    // Define all other row's heights
    this.setRowHeight(0, 45);

    this.d.setTable(this);

    for (int i = 0; i < 5; i++) {
        editor = new AddCellEditor(new JCheckBox(), d.getVisibleDays().get(i), this);
        renderer = new AddCellRenderer(d.getVisibleDays().get(i), editor);
        this.getColumnModel().getColumn(i).setCellRenderer(renderer);
        this.getColumnModel().getColumn(i).setCellEditor(editor);
    }

    this.refresh();
}

public void refresh() {

    // Empty table
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 11; j++) {
            this.getModel().setValueAt(null, j, i);
        }
    }

    // Populate table with entries for each day
    for (int i = 0; i < 5; i++) {

        Iterator<String> iterator = d.getVisibleDays().get(i).getEntryListIterator();

        int j = 0;

        while(iterator.hasNext()){
            String s = iterator.next();
            this.getModel().setValueAt(s, (j+1), i);
            j++;
        }

        this.getModel().setValueAt(d.getVisibleDays().get(i).getDayName(), 0, i);
    }
}

public void modelClearValueAt(int row, int column) {
    this.getModel().setValueAt(null, row, column);
}
}

Cell editor class:

public class AddCellEditor extends DefaultCellEditor {

private JPanel headerPanel;
private JPanel entryPanel;
private JLabel dayName;
private JLabel entryValue;
protected JButton addButton;
private JButton removeButton;
private String label;
private int row;
private int column;
private Day day;
private String date;
private Table table;
private AddCellRenderer renderer;

public AddCellEditor(JCheckBox checkBox, Day day, Table table) {
    super(checkBox);
    this.day = day;
    this.table = table;
    date = day.getDayDate();
    headerPanel = new JPanel();
    headerPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
    entryPanel = new JPanel();
    entryPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
    dayName = new JLabel();
    entryValue = new JLabel();
    addButton = new JButton();
    removeButton = new JButton();
    headerPanel.add(dayName);
    headerPanel.add(addButton);
    entryPanel.add(entryValue);
    entryPanel.add(removeButton);
    addButton.setOpaque(true);
    addButton.setPreferredSize(new Dimension(16, 16));
    removeButton.setOpaque(true);
    removeButton.setPreferredSize(new Dimension(16, 16));
    addButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("Add pressed");
            addItem();
            fireEditingStopped();
        }
    });
    removeButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("Remove pressed");
            removeItem();
            getTable().refresh();
            fireEditingStopped();
        }
    });

}

public void setRenderer(AddCellRenderer renderer) {
    this.renderer = renderer;
}

public Component getTableCellEditorComponent(JTable table, 
        Object value, boolean isSelected, int row, int column) {

    this.row = row;
    this.column = column;

    if (row == 0) {
         return this.headerPanel;
    }
    if (row != 0 && value != null) {
        return this.entryPanel;
    }
    return null;
}

public void addItem() {
    String input = JOptionPane.showInputDialog("Add entry for " + label + ":");

    if ((input != null) && (input.length() > 0)) {
        System.out.println("Added: " + input + "Item");
        day.addEntry(input, column);
    }
}

public void removeItem() {
    table.modelClearValueAt(row, column);
    day.removeEntry(row-1);
    System.out.println("Item removed");
}

public Table getTable() {
    return this.table;
}

public boolean stopCellEditing() {
    return super.stopCellEditing();
}

protected void fireEditingStopped() {
    super.fireEditingStopped();
}
}

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我的黑色迷你裙 2025-01-03 11:55:37

好吧,无法抗拒(另一种方法是擦洗浴室:-)

下面是一个非常原始的大纲(足以给您一个想法),说明如何使用行为良好的编辑器和自定义 tableModel 来解决您的目标。

  • MyTableModel 是一个自定义实现,基本上由任意条目列表支持,
  • 该 tableModel 支持删除/添加项目。目前是私下的,所以您不会想从编辑器中调用它们:-)它们足够安全,可以在需要时在公共范围内公开,如果程序的其他部分需要修改条目,并且
  • 模型可以处理不同的条目setValueAt 中的值类型:修改标记、NewEntry 或普通值
  • 自定义编辑器是一个带有删除、添加行按钮的面板。
  • 按钮的操作在根据需要调用编辑停止/取消之前设置适当的 editorValue

模型:

public static class MyTableModel extends AbstractTableModel {

    public enum Modify {
        ADD,
        REMOVE
    }

    public static class NewItem {
        public final Object entry;

        public NewItem(Object entry) {
            this.entry = entry;
        }
    }

    private List entries;

    public MyTableModel(List entries) {
        this.entries = entries;
    }

    @Override
    public int getRowCount() {
        return entries.size();
    }

    @Override
    public int getColumnCount() {
        return 1;
    }


    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return true;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return entries.get(rowIndex);
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        if (aValue instanceof NewItem) {
            addEntry(((NewItem) aValue).entry);
        } else if (Modify.REMOVE == aValue) {
            removeEntry(rowIndex);
        } else {
            entries.set(rowIndex, aValue);
        }    
    }

    private void removeEntry(int rowIndex) {
        entries.remove(rowIndex);
        fireTableRowsDeleted(rowIndex, rowIndex);
    }

    private void addEntry(Object aValue) {
        int last = getRowCount();
        entries.add(aValue);
        fireTableRowsInserted(last, last);
    }


}

编辑器:

public static class MyCellEditor extends AbstractCellEditor implements TableCellEditor {

    private Object editorValue;
    private JLabel entryView;
    JComponent editor;

    public MyCellEditor() {
        editor = new JPanel();
        entryView = new JLabel();
        editor.add(entryView);
        Action add = createAddAction();
        editor.add(new JButton(add));
        Action remove = createRemoveAction();
        editor.add(new JButton(remove));
    }

    public Action createRemoveAction() {
        Action remove = new AbstractAction("Remove Entry") {

            @Override
            public void actionPerformed(ActionEvent e) {
                editorValue = MyTableModel.Modify.REMOVE;
                fireEditingStopped();
            }

        };
        return remove;
    }

    public Action createAddAction() {
        Action add = new AbstractAction("Add Entry") {

            @Override
            public void actionPerformed(ActionEvent e) {
                String input = JOptionPane.showInputDialog("Add entry: ");

                if ((input != null) && (input.length() > 0)) {
                    editorValue = new MyTableModel.NewItem(input);
                    fireEditingStopped();
                } else {
                    fireEditingCanceled();
                }

            }

        };
        return add;
    }

    @Override
    public Object getCellEditorValue() {
        return editorValue;
    }

    @Override
    public Component getTableCellEditorComponent(JTable table,
            Object value, boolean isSelected, int row, int column) {
        entryView.setText(value != null ? value.toString() : "");
        return editor;
    }


}

用法:

    List entries = new ArrayList();
    for (int i = 0; i < 5; i++) {
        entries.add("entry " + i);
    }
    TableModel model = new MyTableModel(entries);
    JTable table = new JTable(model);
    table.getColumnModel().getColumn(0).setCellEditor(new MyCellEditor());
    table.getColumnModel().getColumn(0).setPreferredWidth(200);
    table.setRowHeight(50);

okay, couldn't resist (the alternative is to scrub the bathroom :-)

Below is a very raw outline (just enough to give you an idea) of how to solve your goal with well-behaved editor and custom tableModel.

  • MyTableModel is a custom implementation basically backed by a List of arbitrary entries
  • this tableModel supports removing/adding items. Privately for now, so you aren't tempted to call them from the editor :-) They are safe enough to expose with public scope, if needed, f.i. if other parts the program need to modify the entries as well
  • the model can handle different value types in setValueAt: a Modify marker, a NewEntry or a plain value
  • the custom editor is a panel with buttons to remove, add a row.
  • the actions of the button set the editorValue as appropriate before calling editingStopped/canceled as needed

The model:

public static class MyTableModel extends AbstractTableModel {

    public enum Modify {
        ADD,
        REMOVE
    }

    public static class NewItem {
        public final Object entry;

        public NewItem(Object entry) {
            this.entry = entry;
        }
    }

    private List entries;

    public MyTableModel(List entries) {
        this.entries = entries;
    }

    @Override
    public int getRowCount() {
        return entries.size();
    }

    @Override
    public int getColumnCount() {
        return 1;
    }


    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return true;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return entries.get(rowIndex);
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        if (aValue instanceof NewItem) {
            addEntry(((NewItem) aValue).entry);
        } else if (Modify.REMOVE == aValue) {
            removeEntry(rowIndex);
        } else {
            entries.set(rowIndex, aValue);
        }    
    }

    private void removeEntry(int rowIndex) {
        entries.remove(rowIndex);
        fireTableRowsDeleted(rowIndex, rowIndex);
    }

    private void addEntry(Object aValue) {
        int last = getRowCount();
        entries.add(aValue);
        fireTableRowsInserted(last, last);
    }


}

The editor:

public static class MyCellEditor extends AbstractCellEditor implements TableCellEditor {

    private Object editorValue;
    private JLabel entryView;
    JComponent editor;

    public MyCellEditor() {
        editor = new JPanel();
        entryView = new JLabel();
        editor.add(entryView);
        Action add = createAddAction();
        editor.add(new JButton(add));
        Action remove = createRemoveAction();
        editor.add(new JButton(remove));
    }

    public Action createRemoveAction() {
        Action remove = new AbstractAction("Remove Entry") {

            @Override
            public void actionPerformed(ActionEvent e) {
                editorValue = MyTableModel.Modify.REMOVE;
                fireEditingStopped();
            }

        };
        return remove;
    }

    public Action createAddAction() {
        Action add = new AbstractAction("Add Entry") {

            @Override
            public void actionPerformed(ActionEvent e) {
                String input = JOptionPane.showInputDialog("Add entry: ");

                if ((input != null) && (input.length() > 0)) {
                    editorValue = new MyTableModel.NewItem(input);
                    fireEditingStopped();
                } else {
                    fireEditingCanceled();
                }

            }

        };
        return add;
    }

    @Override
    public Object getCellEditorValue() {
        return editorValue;
    }

    @Override
    public Component getTableCellEditorComponent(JTable table,
            Object value, boolean isSelected, int row, int column) {
        entryView.setText(value != null ? value.toString() : "");
        return editor;
    }


}

The usage:

    List entries = new ArrayList();
    for (int i = 0; i < 5; i++) {
        entries.add("entry " + i);
    }
    TableModel model = new MyTableModel(entries);
    JTable table = new JTable(model);
    table.getColumnModel().getColumn(0).setCellEditor(new MyCellEditor());
    table.getColumnModel().getColumn(0).setPreferredWidth(200);
    table.setRowHeight(50);
戏蝶舞 2025-01-03 11:55:37

如果您使用的是 DefaultTableModel,则必须删除模型本身保存的值,而不是删除用于构建模型的 ArrayList 中的值。您可以通过调用 DefaultTableModel 对象的 setValueAt(...) 方法来完成此操作。

您可能希望发布 SSCCE 以获得更具体的帮助。

If you're using a DefaultTableModel, then you would have to delete the value held by the model itself, not the value in the ArrayList that was used to build the model. You would do this by calling the setValueAt(...) method of the DefaultTableModel object.

You may wish to post an SSCCE for more specific help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文