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

查看:113
本文介绍了如何在单元格编辑后维护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(),它将调用规定的渲染器。扩展默认应该足以处理数字格式化。在其他情况下,使用渲染器的实例作为编辑器组件可能会很方便;此示例显示了典型的实施方式。

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天全站免登陆