java - 为什么一个 Swing 击键有效,而另一个击键无效?

标签 java swing keystroke

我正在编写一个带有 JTable 的 Swing 程序;我想使用 control-V 粘贴到 JTable 中,并使用 control-S 保存 JTable 上的信息。

我首先使用 JTable.registerKeyboardAction() 使用 control-V 键注册操作,这有效,但我注意到它的 javadoc 说它已过时,新代码应该使用为此目的输入 map 和行动 map 。

我将它们用于 control-S 键,我也将其映射到 JButton,所以我认为它很容易复制。这是我现在用于创建 JFrame 的代码片段:

  private JFrame createMainframe()
  {
    JFrame frame = new JFrame("VisaExtraction");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    String saveFileActionName = "Save";
    String pasteActionName = "Paste";

    Action saveFileAction = new SaveFileAction(saveFileActionName, frame, tableModel);
    Action pasteAction    = new PasteAction(pasteActionName, frame, tableModel);

//    JButton saveButton = new JButton(saveFileAction);
//    saveButton.setMnemonic(KeyEvent.VK_S);

    JPanel topPanel = new JPanel();
//    topPanel.add(saveButton);

    mainTable = new LastColumnChangesWidthJTable(tableModel);
    JScrollPane scrollPane = new JScrollPane(mainTable);

    // set ctrl-s to the 'saveFile' action
    //  and ctrl-v to the 'paste' action
    InputMap  tableInputMap  = mainTable.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

    KeyStroke saveKeystroke  = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK);
    tableInputMap.put(saveKeystroke, saveFileActionName);

    KeyStroke pasteKeystroke = KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK);
    tableInputMap.put(pasteKeystroke, pasteActionName);

    // set the saveFile and paste actions to be executed when invoked.
    ActionMap tableActionMap = mainTable.getActionMap();
    tableActionMap.put(saveFileActionName,  saveFileAction);
    tableActionMap.put(pasteActionName,     pasteAction);

    frame.add(topPanel,   BorderLayout.NORTH);
    frame.add(scrollPane, BorderLayout.CENTER);

    frame.pack();

    // register ctrl-v to paste into the JTable
//    mainTable.registerKeyboardAction
//    ( actionListener -> handlePaste(tableModel, new VisaExtractionListener(tableModel)),
//      KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK), 
//      JComponent.WHEN_IN_FOCUSED_WINDOW
//    );

    return frame;
  }

如您所见,我对“S”和“保存”执行的操作与对“V”和“粘贴”执行的操作相同,但是在启动程序后,“control-S”起作用(在某种程度上告诉我没有什么可保存的)而“control-V”则没有(没有命中 actionPerformed() 方法中的断点)。

是什么导致了这两者之间的差异?

最佳答案

您的问题可能是由于 JTable 已经在另一个输入映射中使用了 ctrl-V 操作。了解码件有 3 个输入映射,并且我相信 JComponent.WHEN_FOCUSED 的输入映射优先于 WHEN_IN_FOCUSED_WINDOW

我的 MCVE 用于概念验证。更改下面代码中的注释字段以查看哪个有效:

import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

import javax.swing.*;

public class Foo {
    public static void main(String[] args) {
        Integer[][] rowData = {{1, 2}, {3, 4}};
        String[] columnNames = {"A", "B"};
        JTable table = new JTable(rowData, columnNames);
        JScrollPane scrollPane = new JScrollPane(table);

        // int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
        int condition = JComponent.WHEN_FOCUSED;
        InputMap inputMap = table.getInputMap(condition);
        ActionMap actionMap = table.getActionMap();

        KeyStroke saveKeystroke  = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK);
        KeyStroke pasteKeystroke = KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK);

        inputMap.put(saveKeystroke, saveKeystroke.toString());
        inputMap.put(pasteKeystroke, pasteKeystroke.toString());

        actionMap.put(saveKeystroke.toString(), new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("save action");
            }
        });
        actionMap.put(pasteKeystroke.toString(), new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("paste action");
            }
        });

        JFrame frame = new JFrame("Foo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(scrollPane);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

将来,创建 MCVE 的工作应该由您来承担,因为您是寻求帮助的人。

编辑:我错了。已经在使用并且让您感到困惑的输入映射是 JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT 映射。在我的 MCVE 更新中,control-V 键有一个非空键字符串:

import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;

public class Foo {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createGui());
    }

    public static void createGui() {
        Integer[][] rowData = { { 1, 2 }, { 3, 4 } };
        String[] columnNames = { "A", "B" };
        JTable table = new JTable(rowData, columnNames);
        JScrollPane scrollPane = new JScrollPane(table);

        int condition = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
        // int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
        // int condition = JComponent.WHEN_FOCUSED;
        InputMap inputMap = table.getInputMap(condition);
        ActionMap actionMap = table.getActionMap();

        KeyStroke saveKeystroke = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK);
        KeyStroke pasteKeystroke = KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK);

        String pasteKey = (String) inputMap.get(pasteKeystroke);
        System.out.println(pasteKey);

        inputMap.put(saveKeystroke, saveKeystroke.toString());
        inputMap.put(pasteKeystroke, pasteKeystroke.toString());

        actionMap.put(saveKeystroke.toString(), new MyAction("Save Action"));
        actionMap.put(pasteKeystroke.toString(), new MyAction("Paste Action"));

        JFrame frame = new JFrame("Foo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(scrollPane);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

@SuppressWarnings("serial")
class MyAction extends AbstractAction {
    private String text;

    public MyAction(String text) {
        this.text = text;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println(text);
    }
}

关于java - 为什么一个 Swing 击键有效,而另一个击键无效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55327001/

相关文章:

java - 如何创建泛型?

Java 为 JTextArea 中的每个新行创建新文本行

java - 从面板中将 jTextArea 添加到 JPanel

java - 如何声明 KeyStroke - 按下和释放?

Java InputMap 不注册 Shift 按键

java - 试图将一堆 C++ 代码转换为 Java - if 语句

java - 如何将纳秒级的正常运行时间转换为可读的日期时间格式

Java日期处理

Java swing mousemove 只触发一次

python - 如何在键盘记录程序中将输出合并到单行中?