【问题标题】:How to maintain JTable cell rendering after cell edit如何在单元格编辑后维护 JTable 单元格渲染
【发布时间】:2012-04-21 11:06:54
【问题描述】:

你们在我最后一个问题上为我指明了正确的方向真是太棒了,我在这里对我的原始问题进行了扩展:

How to set a JTable column as String and sort as Double?

由于我现在使用自定义单元格渲染器将价格列格式化为 $###,##0.00,因此我现在也为单元格设置了 JTextField 编辑器。单元格的编辑工作得很好,除了当值更新时,我的自定义渲染器中设置的数字格式似乎不再格式化单元格(我在提交编辑后丢失了 $)。即使在数据初始显示之后,这个渲染器是否不应该渲染单元格?

我尝试使用以下方法,但没有成功:

((AbstractTableModel) table.getModel()).fireTableDataChanged();

我希望这会强制表格重新验证并使用自定义渲染器重新绘制单元格以渲染新值,但不幸的是这不起作用...

我是不是错过了什么……很明显,但是什么?

【问题讨论】:

    标签: java swing jtable tablecellrenderer tablecelleditor


    【解决方案1】:

    当您的编辑器结束时,表的editingStopped() 方法通过getCellEditorValue() 收集新值并将其用于模型中的setValueAt()。反过来,模型应该fireTableCellUpdated(),它将调用规定的渲染器。扩展default 应该足以处理Number 格式。在其他情况下,使用渲染器的实例作为编辑器组件可能会很方便;这个example 展示了一个典型的实现。

    附录:这是一个使用默认编辑器和渲染器实现的基本示例。

    附录:感谢@mKorbel 提供的帮助,我更新了示例以选择单元格的文本进行编辑,如@camickr 的文章Table Select All Editor 中所述。

    package overflow;
    
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.event.MouseEvent;
    import java.text.NumberFormat;
    import java.util.EventObject;
    import javax.swing.DefaultCellEditor;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.JTextField;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.DefaultTableModel;
    import javax.swing.text.JTextComponent;
    
    /** @see http://stackoverflow.com/a/10067560/230513 */
    public class RenderEditNumber extends JPanel {
    
        private NumberFormat nf = NumberFormat.getCurrencyInstance();
    
        public RenderEditNumber() {
            DefaultTableModel model = new DefaultTableModel(
                new String[]{"Amount"}, 0) {
    
                @Override
                public Class<?> getColumnClass(int columnIndex) {
                    return Double.class;
                }
            };
            for (int i = 0; i < 16; i++) {
                model.addRow(new Object[]{Double.valueOf(i)});
            }
            JTable table = new JTable(model) {
    
                @Override // Always selectAll()
                public boolean editCellAt(int row, int column, EventObject e) {
                    boolean result = super.editCellAt(row, column, e);
                    final Component editor = getEditorComponent();
                    if (editor == null || !(editor instanceof JTextComponent)) {
                        return result;
                    }
                    if (e instanceof MouseEvent) {
                        EventQueue.invokeLater(new Runnable() {
    
                            @Override
                            public void run() {
                                ((JTextComponent) editor).selectAll();
                            }
                        });
                    } else {
                        ((JTextComponent) editor).selectAll();
                    }
                    return result;
                }
            };
            table.setPreferredScrollableViewportSize(new Dimension(123, 123));
            table.setDefaultRenderer(Double.class, new CurrencyRenderer(nf));
            table.setDefaultEditor(Double.class, new CurrencyEditor(nf));
            this.add(new JScrollPane(table));
        }
    
        private static class CurrencyRenderer extends DefaultTableCellRenderer {
    
            private NumberFormat formatter;
    
            public CurrencyRenderer(NumberFormat formatter) {
                this.formatter = formatter;
                this.setHorizontalAlignment(JLabel.RIGHT);
            }
    
            @Override
            public void setValue(Object value) {
                setText((value == null) ? "" : formatter.format(value));
            }
        }
    
        private static class CurrencyEditor extends DefaultCellEditor {
    
            private NumberFormat formatter;
            private JTextField textField;
    
            public CurrencyEditor(NumberFormat formatter) {
                super(new JTextField());
                this.formatter = formatter;
                this.textField = (JTextField) this.getComponent();
                textField.setHorizontalAlignment(JTextField.RIGHT);
                textField.setBorder(null);
            }
    
            @Override
            public Object getCellEditorValue() {
                try {
                    return new Double(textField.getText());
                } catch (NumberFormatException e) {
                    return Double.valueOf(0);
                }
            }
    
            @Override
            public Component getTableCellEditorComponent(JTable table,
                Object value, boolean isSelected, int row, int column) {
                textField.setText((value == null)
                    ? "" : formatter.format((Double) value));
                return textField;
            }
        }
    
        private void display() {
            JFrame f = new JFrame("RenderEditNumber");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(this);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    new RenderEditNumber().display();
                }
            });
        }
    }
    

    【讨论】:

    • +1 但我看到,如果你想添加、删除或编辑存在的值,在无法正常工作之前,编辑器返回 0.00 :-),我必须看看....跨度>
    • 好点。对于矩阵输入,编辑器有意在NumberFormatException 上返回零; cancelCellEditing() 将是更通用的选择。
    • 这对于 JFormattedTextField 或 JSpinner 和 CellEditor 是一样的,我确定 Rob 已经得到了……,你必须返回 Document,Rob 你在哪里 :-)
    • 我不明白;我通常只是点击退出来取消编辑。
    • 请查看我的代码here,一切正常,但如果我将 CurrencyInstance 放在那里而不是 NumberInstance,那么我的代码将用于编辑,您的代码用于选择整个值并替换为新的... ,现在不知道为什么...
    猜你喜欢
    • 2012-08-05
    • 2011-10-02
    • 1970-01-01
    • 1970-01-01
    • 2014-06-26
    • 2010-12-07
    • 2019-04-30
    • 1970-01-01
    • 2011-09-27
    相关资源
    最近更新 更多