JTable 键监听器
JTable Key Listener
我需要我的 JTable 来验证给定行的数据并将列 1 的组件更改为标记为 "Save"(准备保存记录)的 JButton,如果验证确定数据正常的话。我需要对每次击键做出反应。
无论我尝试了多少方法,用户似乎都必须在评估数据之前关闭单元格编辑器(通过单击其他地方或按 Enter)。
您是否知道有一种关键侦听器(或其他方法)可以提供即时反馈而不是强迫这种额外的 key/mouse 敲击?
使用 DefaultCellEditor 的数据评估仍然需要这个额外的击键,而 KeyBindings(显然不需要)似乎只需要对特定的键做出反应。
有没有办法提供一个侦听器,它会立即对编辑器中的每个击键做出反应?
跟进 m0skit0 的问题
问:我尝试了什么?
A:我有一个名为 ButtonColumn 的 class,改编自 Rob Camick,它实现了 TableCellRenderer。
这会验证行数据,如果验证成功,它会将单元格呈现为标记为“保存”的 JButton,否则它 returns 具有纯文本标签“新建...”(红色字体)的 theDefaultRendererComponent .
我有另一个 class 实现了 KeyListener,它会在用户每次击键时重新绘制 table,从而执行 SaveButtonRowFormatter 验证和呈现(如上所述)。
这有效,但只有在 的单元格编辑器关闭后才有效。这就是问题所在:用户必须完成关闭编辑器的工作才能呈现 table 并显示保存按钮。这是不直观的,因为没有明显的理由说明为什么用户在确定他们已成功填写记录后会进行任何击键。此时没有任何保存按钮,它们被卡住了
最简单的方法是使用:
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
否则,您可以执行以下操作:
在你的 ActionListener
按钮中,你可以简单地做 if(table.getCellEditor()!=null) table.getCellEditor().stopCellEditing();
请参阅此示例,先打印模型,然后再打印模型。
尝试一下,只需开始编辑任何单元格,然后按 "Save"(不要点击其他任何地方或取消编辑状态),您会看到控制台中的输出不同(第二个输出考虑了您所做的最后修改)。
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
public class TestEditableTable {
protected void initUI() {
JFrame frame = new JFrame(TestEditableTable.class.getSimpleName());
Vector<Vector<String>> data = new Vector<Vector<String>>();
for (int i = 0; i < 2; i++) {
Vector<String> row = new Vector<String>();
for (int j = 0; j < 5; j++) {
row.add("Cell " + i + "," + j);
}
data.add(row);
}
Vector<String> columns = new Vector<String>();
for (int j = 0; j < 5; j++) {
columns.add("Column " + j);
}
final TableModel model = new DefaultTableModel(data, columns);
final JTable table = new JTable(model);
frame.add(new JScrollPane(table), BorderLayout.CENTER);
JButton save = new JButton("Save");
save.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
printDataModel(model);
if (table.getCellEditor() != null) {
table.getCellEditor().stopCellEditing();
}
printDataModel(model);
}
private void printDataModel(final TableModel model) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < model.getRowCount(); i++) {
for (int j = 0; j < model.getColumnCount(); j++) {
sb.append(model.getValueAt(i, j)).append(' ');
}
sb.append("\n");
}
System.out.println(sb);
}
});
frame.add(save, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TestEditableTable().initUI();
}
});
}
}
Is there a way to provide a listener that will react instantly to each keystroke in the editor?
在编辑器的编辑器组件中添加一个 DocumentListener。
DefaultCellEditor dce = (DefaultCellEditor)table.getDefaultEditor(Object.class);
JTextField textField = (JTextField)dce.getComponent();
textField.getDocument().addDocumentListener(...);
阅读 How to Write a Document Listener 上的 Swing 教程部分了解更多信息。
我需要我的 JTable 来验证给定行的数据并将列 1 的组件更改为标记为 "Save"(准备保存记录)的 JButton,如果验证确定数据正常的话。我需要对每次击键做出反应。
无论我尝试了多少方法,用户似乎都必须在评估数据之前关闭单元格编辑器(通过单击其他地方或按 Enter)。
您是否知道有一种关键侦听器(或其他方法)可以提供即时反馈而不是强迫这种额外的 key/mouse 敲击?
使用 DefaultCellEditor 的数据评估仍然需要这个额外的击键,而 KeyBindings(显然不需要)似乎只需要对特定的键做出反应。
有没有办法提供一个侦听器,它会立即对编辑器中的每个击键做出反应?
跟进 m0skit0 的问题
问:我尝试了什么?
A:我有一个名为 ButtonColumn 的 class,改编自 Rob Camick,它实现了 TableCellRenderer。
这会验证行数据,如果验证成功,它会将单元格呈现为标记为“保存”的 JButton,否则它 returns 具有纯文本标签“新建...”(红色字体)的 theDefaultRendererComponent .
我有另一个 class 实现了 KeyListener,它会在用户每次击键时重新绘制 table,从而执行 SaveButtonRowFormatter 验证和呈现(如上所述)。
这有效,但只有在 的单元格编辑器关闭后才有效。这就是问题所在:用户必须完成关闭编辑器的工作才能呈现 table 并显示保存按钮。这是不直观的,因为没有明显的理由说明为什么用户在确定他们已成功填写记录后会进行任何击键。此时没有任何保存按钮,它们被卡住了
最简单的方法是使用:
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
否则,您可以执行以下操作:
在你的 ActionListener
按钮中,你可以简单地做 if(table.getCellEditor()!=null) table.getCellEditor().stopCellEditing();
请参阅此示例,先打印模型,然后再打印模型。
尝试一下,只需开始编辑任何单元格,然后按 "Save"(不要点击其他任何地方或取消编辑状态),您会看到控制台中的输出不同(第二个输出考虑了您所做的最后修改)。
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
public class TestEditableTable {
protected void initUI() {
JFrame frame = new JFrame(TestEditableTable.class.getSimpleName());
Vector<Vector<String>> data = new Vector<Vector<String>>();
for (int i = 0; i < 2; i++) {
Vector<String> row = new Vector<String>();
for (int j = 0; j < 5; j++) {
row.add("Cell " + i + "," + j);
}
data.add(row);
}
Vector<String> columns = new Vector<String>();
for (int j = 0; j < 5; j++) {
columns.add("Column " + j);
}
final TableModel model = new DefaultTableModel(data, columns);
final JTable table = new JTable(model);
frame.add(new JScrollPane(table), BorderLayout.CENTER);
JButton save = new JButton("Save");
save.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
printDataModel(model);
if (table.getCellEditor() != null) {
table.getCellEditor().stopCellEditing();
}
printDataModel(model);
}
private void printDataModel(final TableModel model) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < model.getRowCount(); i++) {
for (int j = 0; j < model.getColumnCount(); j++) {
sb.append(model.getValueAt(i, j)).append(' ');
}
sb.append("\n");
}
System.out.println(sb);
}
});
frame.add(save, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TestEditableTable().initUI();
}
});
}
}
Is there a way to provide a listener that will react instantly to each keystroke in the editor?
在编辑器的编辑器组件中添加一个 DocumentListener。
DefaultCellEditor dce = (DefaultCellEditor)table.getDefaultEditor(Object.class);
JTextField textField = (JTextField)dce.getComponent();
textField.getDocument().addDocumentListener(...);
阅读 How to Write a Document Listener 上的 Swing 教程部分了解更多信息。