单元格编辑后如何维护JTable单元格渲染 [英] How to maintain JTable cell rendering after cell edit

查看:40
本文介绍了单元格编辑后如何维护JTable单元格渲染的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你们在我上一个问题的正确方向上非常棒,我在这里对我的原始问题进行了扩展:

You guys were so awesome in point me in the right direction on my last question and I have sort of an extension of my original question here:

如何设置 JTable列为 String 并按 Double 排序?

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

As I now have my price column formatted as $###,##0.00 by using my custom cell renderer, I have now set up a JTextField Editor for the cell as well. The editing of the cell works just fine except for when the value is updated, the number format set in my custom renderer no longer seems to format the cell (I'm loosing the $ after edit is committed). Is this renderer not supposed to render the cells even after the initial display of the data?

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

I have tried to use the following with no luck:

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

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

I was hoping that this would force the table to revalidate and repaint the cells using the custom renderer to render the new values, but this unfortunately did not work...

我是否遗漏了什么......显然,但什么?

Am I missing something... Obviously, but what?

推荐答案

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

When your editor concludes, the table's editingStopped() method collects the new value via getCellEditorValue() and uses it to setValueAt() in the model. The model, in turn, should fireTableCellUpdated(), which will invoke the prescribed renderer. Extending the default should be enough to handle Number formatting. In other cases, it may be convenient to use an instance of your renderer as your editor component; this example shows a typical implementation.

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

Addendum: Here's a basic example using the default editor and renderer implementations.

附录:感谢@mKorbel 的有用评论,我更新了示例以选择单元格的文本进行编辑,如@camickr 的文章 表格全选编辑器.

Addendum: Thanks to helpful comments from @mKorbel, I've updated the example to select the cell's text for editing, as described in @camickr's article 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();
            }
        });
    }
}

这篇关于单元格编辑后如何维护JTable单元格渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆