java 单元格编辑后如何维护JTable单元格渲染
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10067060/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to maintain JTable cell rendering after cell edit
提问by titanic_fanatic
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:
你们太棒了,在我的最后一个问题上为我指出了正确的方向,我在这里对我的原始问题进行了扩展:
How to set a JTable column as String and sort as Double?
如何将 JTable 列设置为 String 并按 Double 排序?
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?
由于我现在使用自定义单元格渲染器将价格列格式化为 $###,##0.00,因此我现在也为单元格设置了 JTextField 编辑器。单元格的编辑工作正常,除了值更新时,在我的自定义渲染器中设置的数字格式似乎不再格式化单元格(我在提交编辑后丢失了 $)。即使在初始显示数据之后,此渲染器也不应该渲染单元格吗?
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?
我错过了什么......显然,但什么?
回答by trashgod
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 defaultshould 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 exampleshows a typical implementation.
当您的编辑器结束时,表的editingStopped()
方法通过收集新值getCellEditorValue()
并将其用于setValueAt()
模型中。反过来,模型应该 fireTableCellUpdated()
调用指定的渲染器。扩展默认值应该足以处理Number
格式。在其他情况下,使用渲染器的实例作为编辑器组件可能会很方便;这个例子展示了一个典型的实现。
Addendum: Here's a basic example using the default editor and renderer implementations.
附录:这是一个使用默认编辑器和渲染器实现的基本示例。
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.
附录:感谢来自@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();
}
});
}
}