我在JTable中有一个功能,当用户点击单元格时,它会删除其中的某些字符(例如当内容为- Hello
时,当用户点击它时,它会显示Hello
)。如果不再进行编辑,则会再次显示- Hello
。
我的问题是,当选择某个单元格(但尚未编辑)并且我开始键入Hi
时,它不会删除该字符,因此可编辑单元格看起来像- Hello Hi
。< / p>
同样的问题是当选择某个单元格并且用户按空格键时。
我想将功能添加到JTable中,以便在开始编辑单元格的内容时(以任何方式 - 选中时单击/键入/空格键/也许还有更多选项我不知道关于),我想先以编程方式更改内容。另一种选择是在选择单元格时删除它(但是我必须记住最后一个选定单元格的位置,以便可以将字符读回到它)。
我在类TableChangeListener中尝试了propertyChange:
table.setValueAt(removeCharacter(table.getValueAt(row,column)), row, column);
但它不起作用,因为单元格已被编辑,我无法更改它。
答案 0 :(得分:2)
FocusLisetener
和ActionListener
的自定义CellEditor,并实施FocusGained
和FocusLost
功能actionPerformed
功能以更新输入点击值。CellEditor
并读取单元格行,聚焦焦点增益。- xxxx
:在单元格值之前放置-
,请尝试使用自定义CellRenderer
。有关详细信息,请查看official tutorial page示例。而部分功劳归功于@mKobel。 用于方向的已实现的自定义单元格编辑器:将其分配给目标表列并进行测试。
我测试结果的Giff:
<强>代码:强>
class CustomRenderer extends DefaultTableCellRenderer {
public void setValue(Object value)
{
setText("- "+value);
}
}
class MyCellEditor extends AbstractCellEditor
implements TableCellEditor,
FocusListener,
ActionListener
{
JTextField textFeild;
String currentValue;
JTable table;
int row, col;
public MyCellEditor(JTable table) {
this.table = table;
textFeild = new JTextField();
textFeild.addActionListener(this);
textFeild.addFocusListener(this);
}
@Override
public Object getCellEditorValue() {
return currentValue;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
currentValue = (String)value;
return textFeild;
}
@Override
public void focusGained(FocusEvent e) {
textFeild.setText("");
row = table.getSelectedRow();
col = table.getSelectedColumn();
}
@Override
public void focusLost(FocusEvent e) {
if(!textFeild.getText().equals(""))
//currentValue = textFeild.getText();
table.setValueAt(textFeild.getText(), row, col);
fireEditingStopped();
}
@Override
public void actionPerformed(ActionEvent e) {
if(!textFeild.getText().trim().equals(""))
currentValue = textFeild.getText();
fireEditingStopped();
}
}
答案 1 :(得分:1)
我认为你根本不应该更改单元格的内容。
你需要的是在表格上设置一个呈现单元格值的TableCellRenderer
。实现单元格渲染器,使其显示值“ - Hello”(尽管您的实际数据可能只包含“Hello”)。渲染器只显示表中所需的任何组件。当用户开始编辑单元格时,不显示渲染器组件。实际上,您也可以使用TableCellEditor
操作编辑组件。
答案 2 :(得分:1)
摘自this comment:
该表显示价格“$ 5”“20€”以及用户点击单元格时的价格 为了改变价格,我希望这个标志消失。当用户 完成编辑(点击输入或通过其他方式),我想要符号 再次出现。
虽然@Sage帖子是一个非常好的通用解决方案(+1给你:),在这种特殊情况下,我会使用TableCellRenderer来实现TableCellEditor和JFormattedTextField管理货币格式问题,如下:
这样,当显示单元格时,将显示货币符号,但在编辑单元格时,货币符号将“消失”。
看看这个实施的例子:
import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.text.NumberFormat;
import java.util.EventObject;
import java.util.Locale;
import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.JFormattedTextField;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.text.NumberFormatter;
public class CurrencyEditor extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
JFormattedTextField editor;
JFormattedTextField renderer;
Integer clickCountToStart = 2;
public CurrencyEditor(Locale locale) {
initEditor(locale);
initRenderer(locale);
}
private void initRenderer(Locale locale) {
NumberFormat format = locale != null ?
NumberFormat.getCurrencyInstance(locale) : NumberFormat.getCurrencyInstance();
NumberFormatter formatter = new NumberFormatter(format);
formatter.setMinimum(Double.MIN_VALUE);
formatter.setMaximum(Double.MAX_VALUE);
formatter.setAllowsInvalid(false);
renderer = new JFormattedTextField(formatter);
}
private void initEditor(Locale locale) {
NumberFormat format = locale != null ?
NumberFormat.getNumberInstance(locale) : NumberFormat.getNumberInstance();
NumberFormatter formatter = new NumberFormatter(format);
formatter.setMinimum(Double.MIN_VALUE);
formatter.setMaximum(Double.MAX_VALUE);
formatter.setAllowsInvalid(false);
editor = new JFormattedTextField(formatter);
editor.setBorder(UIManager.getBorder("Tree.editorBorder"));
}
@Override
public Object getCellEditorValue() {
return editor.getValue();
}
@Override
public boolean isCellEditable(EventObject anEvent) {
if (anEvent instanceof MouseEvent) {
return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;
}
return true;
}
@Override
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
@Override
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
if(value instanceof Double){
editor.setValue(value);
}
return editor;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if(value instanceof Double) {
Color background = isSelected ? UIManager.getColor("Table.selectionBackground") : UIManager.getColor("Table.background");
Color foreground = isSelected ? UIManager.getColor("Table.selectionForeground") : UIManager.getColor("Table.foreground");
Border border = hasFocus ? UIManager.getBorder("Table.focusCellHighlightBorder") : BorderFactory.createEmptyBorder();
renderer.setBackground(background);
renderer.setForeground(foreground);
renderer.setBorder(border);
renderer.setValue(value);
return renderer;
} else {
String message = String.format("Not supported for %1$1s class!", value.getClass());
throw new IllegalArgumentException(message);
}
}
}
免责声明:由于UIManager属性命名不同,因此可能无法正常使用Nimbus外观。我使用Metal,Windows,Windows Classic和Motif进行了测试。
以下是我用来测试它的代码:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Locale;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
public class Demo {
private void initGUI(){
DefaultTableModel model = new DefaultTableModel(new Object[]{"Item", "Price USD", "Price EUR"}, 0);
model.addRow(new Object[]{"Fender stratocaster", 1599.99d, 1176.46d});
model.addRow(new Object[]{"Gibson Les Paul", 1299.99d, 955.87d});
model.addRow(new Object[]{"Pual Reed Smith Standard 24", 1999.99d, 1470.58d});
JTable table = new JTable(model);
table.setPreferredScrollableViewportSize(new Dimension(500, 300));
TableColumn priceUSD = table.getColumn("Price USD");
priceUSD.setCellRenderer(new CurrencyEditor(Locale.US));
priceUSD.setCellEditor(new CurrencyEditor(Locale.US));
TableColumn priceEUR = table.getColumn("Price EUR");
priceEUR.setCellRenderer(new CurrencyEditor(Locale.GERMANY));
priceEUR.setCellEditor(new CurrencyEditor(Locale.GERMANY));
JPanel content = new JPanel(new BorderLayout());
content.add(new JScrollPane(table));
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Demo().initGUI();
}
});
}
}