java - 包裹在 JPanel 内的 JScrollPane 内的 JTable 无法捕获 KeyEvent

标签 java swing jtable

我遇到的问题是我的扩展类无法捕获 KeyEvent。这是代码:

public class DatabaseJTable extends JTable implements KeyListener {
    public DatabaseJTable(Object [][] data, Object [] columnNames) {
        super(data, columnNames);
    }

    @Override
    public boolean isCellEditable(int row, int column) {
       return false;
    }

    @Override
    public void keyPressed(KeyEvent kv) {
        // TODO Auto-generated method stub
        if (kv.getKeyChar() == KeyEvent.VK_F2) {
            int selectedRow = this.getSelectedRow();
            System.out.println(this.getModel().getValueAt(selectedRow, 1));
        }
    }

    @Override
    public void keyReleased(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyTyped(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }
}

以下是该类的使用方式:

public class DatabaseRecordScreen extends JPanel {
    public DatabaseRecordScreen() {
        String [] columnNames = {"Date", "Order Number", "Item Number", "Contact", "Client", "Quantity"};
        Object [][] data = getAllWorkOrders();
        DatabaseJTable dataTable = new DatabaseJTable(data, columnNames);
        dataTable.setPreferredScrollableViewportSize(new Dimension(500, 70));
        dataTable.setFillsViewportHeight(true);

        JScrollPane scrollPane = new JScrollPane(dataTable);       
        scrollPane.setPreferredSize(Furniture.MAX_PANEL_SIZE);
        this.setPreferredSize(Furniture.MAX_PANEL_SIZE);
        this.add(scrollPane);
    }
}

DatabaseJTable 无法捕获任何 KeyEvent。我在 KeyPressed 方法的开头调试并设置了断点。但它永远不会被捕获。

如果我遗漏了任何内容,请您告诉我并建议我如何解决此问题。谢谢。

最佳答案

KeyListener 因变化无常而臭名昭著。为了工作,它们注册的组件不仅必须是可聚焦的,而且必须具有焦点才能工作。

更好的解决方案是使用 key bindings API ,例如。

enter image description here

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;

public class TableKeyBindings {

    public static void main(String[] args) {
        new TableKeyBindings();
    }

    public TableKeyBindings() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                DefaultTableModel model = new DefaultTableModel(new String[]{"Row", "Name"}, 0);
                String[] names = new String[]{
                    "Lyveb", "Eldw", "Sutaw", "Radine", "Namhin", "Draos", "Et'rad",
                    "Deloef'c", "Ashlyeu", "Urner", "Nalund", "Rothem", "En'saya", "Torelm",
                    "Sulyc-it", "Ranray", "Denehin", "Zhayss", "Untechustos", "Aldh", "Tastintin",
                    "Burl", "Lyeril", "Trohliss", "Lehub", "Feyef", "Tutsul", "Ingjsam",
                    "When", "Worunde", "Ashtai", "Undoc", "Nyril", "Ightigar", "Umach",
                    "Ceracki", "Ler'elda", "Ray'vesa", "Echril", "Chrorodang", "Oskim", "Mos'tas",
                    "Siusk", "Yertas", "Queler", "Parehy", "Essr", "Shyhon", "Inep",
                    "Yeraer", "Inand", "Osutur", "Aryny", "Vycel", "Roolt", "Ceriss-kin",
                    "Age'augha", "Lelysa", "Ahaty", "Engpolskel", "Kulal", "Ardlper", "Lonuru",
                    "Belyf", "Chroozis", "Rodir", "Dralech", "Undvorrod", "Aqueo", "Yshya",
                    "Eldrad", "Umbur", "Ina'pola", "Hon'er", "Rientai", "Wareph", "Urnil'l",
                    "Et'inee", "Kyest", "Rodinga", "Yenet", "Fothund", "Ackgcer", "Estbanos",
                    "Seroughrad", "Nyer", "Tortiatia", "Dosac", "Moimash", "Whiril", "Oundi",
                    "Sayangrak", "Taqh", "Fidad", "Elmom", "Sayvera", "Imsayo", "Elmsam",
                    "Hubame", "Phorileng", "Bel'ves", "Awit", "Kelvesonhin", "Ingpol", "Ough'ther",
                    "Inaine", "Rilck", "Shys", "Ightl", "Vesangar", "Queineo", "Jyunt",
                    "Aleack", "Ageat", "Cysod", "Deluju", "Oldl", "Alent", "Tia'dele"};

                int row = 0;
                for (String name : names) {
                    model.addRow(new String[]{Integer.toString(++row), name});
                }

                JTable table = new JTable(model);
                InputMap inputMap = table.getInputMap(JComponent.WHEN_FOCUSED);
                ActionMap actionMap = table.getActionMap();

                inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), "Show");
                actionMap.put("Show", new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        JTable table = (JTable)e.getSource();
                        int row = table.getSelectedRow();
                        if (row != -1) {

                            row = table.convertRowIndexToModel(row);
                            String name = (String) table.getModel().getValueAt(row, 1);

                            JOptionPane.showMessageDialog(null, name, "Show", JOptionPane.INFORMATION_MESSAGE);

                        }
                    }
                });

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}

现在,您遇到问题的其他原因之一是 kv.getKeyChar() == KeyEvent.VK_F2 不可比较,即键 char 不会匹配 VK 值,它们唯一的关系是名称。

我认为您可能更喜欢使用kv.getKeyCode(),但是使用键绑定(bind)您会取得更大的成功...

关于java - 包裹在 JPanel 内的 JScrollPane 内的 JTable 无法捕获 KeyEvent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19828059/

相关文章:

Java、Swing、获取和更改所有输入字段

java - 修改 JTable 以适合屏幕

java - 参数化数据结构以保存特定大小的数组?

java - getAction() 只给出 ACTION_DOWN

java - 通过 javax.swing.text.Element 从 JTextPane 获取一个组件?

java - 将焦点设置在jtable中的指定行上

java - 单击按钮时显示表格

java - 如何 "slice"一个POJO

java - 写入文件中的特定行,不带任何数据格式

java - 如何使用 java 中的 XMLEndcoder 在 xml 文件中编写包含数据的 JTable 状态