JTable Key Listener

时间:2015-02-14 18:22:11

标签: java swing jtable key-bindings

我需要我的JTable验证给定行的数据并将column1的组件更改为JButton,标记为" Save" (准备记录保存),如果验证确定数据正常。我需要对每次按键做出反应。

无论我尝试过多少东西,用户似乎都被迫关闭单元格编辑器(通过点击其他地方或按Enter键),然后才能评估数据。

您是否知道有一种方法可以提供即时反馈的关键监听器(或其他方法),而不是强制执行此额外的键/鼠标操作?

使用DefaultCellEditor的数据评估仍然需要这个额外的击键,而KeyBindings(显然没有)似乎只需要对特定键做出反应。

有没有办法提供一个能够立即对编辑器中每次按键做出反应的监听器?

跟进m0skit0的问题

问:我试过了什么?

答:我有一个名为ButtonColumn的类,改编自Rob Camick,它实现了TableCellRenderer。

这会验证行数据,如果验证成功,它会将单元格呈现为标记为“Save”的JButton,ELSE会返回带有纯文本标签“New ...”的theDefaultRendererComponent(红色字体)。

我有另一个实现KeyListener的类,每次用户进行击键时都会重新绘制表格,从而执行SaveButtonRowFormatter验证和渲染(如上所述)。

这只有在单元格编辑器关闭后才有效。这就是问题所在:用户必须完成关闭编辑器的工作才能呈现表格并显示保存按钮。这并不直观,因为没有明显的理由说明用户在确定已成功填写记录后会进行任何击键。此时没有任何保存按钮,它们会被卡住

2 个答案:

答案 0 :(得分:2)

最简单的方法是使用:

table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

否则,您可以执行以下操作:

在按钮的ActionListener中,您只需执行if(table.getCellEditor()!=null) table.getCellEditor().stopCellEditing();

即可

请参阅此示例,首先在执行此操作之前打印模型,然后再打印模型。

要尝试,只需开始编辑任何单元格,然后按"保存" (无需点击其他任何地方或取消编辑状态),您将看到控制台中的输出不同(第二个输出会考虑您最后的修改)。

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();
            }
        });
    }
}

答案 1 :(得分:2)

  

有没有办法提供一个能够立即对编辑器中每次按键做出反应的监听器?

将DocumentListener添加到编辑器的编辑器组件中。

DefaultCellEditor dce = (DefaultCellEditor)table.getDefaultEditor(Object.class);
JTextField textField = (JTextField)dce.getComponent();
textField.getDocument().addDocumentListener(...);

阅读How to Write a Document Listener上的Swing教程中的部分以获取更多信息。