Java 在用户单击单元格时向其添加内容
我在JTable中有一个功能,当用户单击单元格时,它会删除其中的某些字符(比如当有内容Java 在用户单击单元格时向其添加内容,java,swing,jtable,cell,changelistener,Java,Swing,Jtable,Cell,Changelistener,我在JTable中有一个功能,当用户单击单元格时,它会删除其中的某些字符(比如当有内容-Hello,当用户单击它时,它会显示Hello)。不再编辑时,它会再次显示-Hello 我的问题是,当某个单元格被选中(但尚未编辑)并且我开始键入Hi,它不会删除字符,因此可编辑单元格看起来像-Hello Hi 同样的问题是,当选择某个单元格时,用户按空格键 我想在JTable中添加功能,这样当单元格的内容开始被编辑时(通过任何方式-点击/选择时键入/空格键/可能还有更多我不知道的选项),我想先通过编程更改内
-Hello
,当用户单击它时,它会显示Hello
)。不再编辑时,它会再次显示-Hello
我的问题是,当某个单元格被选中(但尚未编辑)并且我开始键入Hi
,它不会删除字符,因此可编辑单元格看起来像-Hello Hi
同样的问题是,当选择某个单元格时,用户按空格键
我想在JTable中添加功能,这样当单元格的内容开始被编辑时(通过任何方式-点击/选择时键入/空格键/可能还有更多我不知道的选项),我想先通过编程更改内容。另一个选项是在选中单元格时将其删除(但我必须记住最后一个选定单元格的位置,以便将字符读入其中)
我在类TableChangeListener中尝试了propertyChange:
table.setValueAt(removeCharacter(table.getValueAt(row,column)), row, column);
但是它不起作用,因为单元格已经被编辑,我无法更改它。我认为您根本不应该更改单元格的内容。
您需要在表上设置一个呈现单元格值的
TableCellRenderer
。实现单元渲染器,使其显示值“-Hello”(尽管实际数据可能只包含“Hello”)。渲染器只显示表中所需的任何组件。当用户开始编辑单元格时,不会显示渲染器组件。实际上,您也可以使用TableCellEditor
操作编辑组件。我认为您根本不应该更改单元格的内容。
您需要在表上设置一个呈现单元格值的TableCellRenderer
。实现单元渲染器,使其显示值“-Hello”(尽管实际数据可能只包含“Hello”)。渲染器只显示表中所需的任何组件。当用户开始编辑单元格时,不会显示渲染器组件。实际上,您还可以使用TableCellEditor
操作编辑组件
FocusLisetener
和ActionListener
并实现FocusGovered
和FocusLost
功能actionPerformed
功能,以在按下enter键时更新值CellEditor
,并读取单元格行col on Focus gain-xxxx
:将-
放在单元格值之前,请尝试使用自定义的单元格渲染器。查看示例以了解详细信息。这部分功劳归@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();
}
}
代码:
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();
}
}
您必须使用自己的单元编辑器实现来满足自己的需求集
因此,创建一个自定义CellEditor,实现FocusLisetener
和ActionListener
并实现FocusGovered
和FocusLost
功能
执行actionPerformed
功能,以在按下enter键时更新值
处理焦点事件有点棘手。因为它会错误地更新单元格。这就是为什么我必须将引用表作为构造函数参数传递给CellEditor
,并读取单元格行col on Focus gain
要反映-xxxx
:将-
放在单元格值之前,请尝试使用自定义的单元格渲染器。查看示例以了解详细信息。这部分功劳归@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();
}
}
代码:
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();
}
}
摘自:
该表显示了“5美元”“20欧元”等价格,以及用户单击单元格时的价格
要改变价格,我想让标志消失。当用户
完成编辑(单击enter或其他方式),我希望符号
再次出现
尽管@Sage post是一个非常好的通用解决方案(+1:),但在这种情况下,我将实现一个和使用它来管理货币格式问题,如下所示:
- 为渲染器组件设置常规数字格式:
- 为编辑器组件设置货币编号格式:
这样,当显示单元格时,将显示货币符号,但当编辑单元格时,货币符号将“消失”
请看以下实施示例:
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);
}
}
}
免责声明:它可能无法与Nimbus外观一起正常工作,因为UIManager属性的名称不同。我用金属、窗户、经典窗户和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();
}
});
}
}
截图
摘自:
该表显示了“5美元”“20欧元”等价格,以及用户单击单元格时的价格
要改变价格,我想让标志消失。当用户
完成编辑(单击enter或其他方式),我希望符号
再次出现
尽管@Sage post是一个非常好的通用解决方案(+1:),但在这种情况下,我将实现一个和使用它来管理货币格式问题,如下所示:
- 为渲染器组件设置常规数字格式:
- 为编辑器组件设置货币编号格式:
这样当cel