Windows 和 Mac 在密钥检测方面的 Java 差异

Posted

技术标签:

【中文标题】Windows 和 Mac 在密钥检测方面的 Java 差异【英文标题】:Java difference in key detection between Windows and Mac 【发布时间】:2012-04-16 02:20:54 【问题描述】:

我有一个带有键侦听器的 JList,以便用户可以轻松地从列表中删除项目。在 Windows 上,它工作正常。您按下删除键,该项目被删除。在 mac 上,程序不响应删除键。我正在使用KeyEvent.VK_DELETE,我认为这是一种检测特殊键的平台中立方式。我应该以其他方式检测 Mac 上的按键吗?

    studentJList.setModel(studentListModel);  // a custom model I wrote
    studentJList.addKeyListener(new KeyListener() 
        @Override
        public void keyPressed(KeyEvent e) 
            if (e.getKeyCode() == KeyEvent.VK_DELETE) 
                studentListModel.remove(studentJList.getSelectedIndex());
                studentJList.revalidate();
            
        

        @Override
        public void keyReleased(KeyEvent e)  

        @Override
        public void keyTyped(KeyEvent e)  
    );

【问题讨论】:

【参考方案1】:

使用keybindings 代替关键侦听器,所有平台上的行为都相同。

另请参阅KeyAdapter listener works in Windows, not on Mac,这或多或少是相同的问题,解决方案也适用于您的问题。

【讨论】:

谢谢。我以前从未接触过 keyBindings,但本教程让它看起来很简单。不过,我不明白为什么 keyListener 不应该工作。 @mKorbel - 感谢您发布此代码示例。 在链接的问题中,其他人提出了 Windows 和 OSX 之间焦点行为存在差异的可能性。并且 keylistener 需要在触发之前获得焦点 @Thorn 确保你遵循 (@kleopatra) 的好建议,这些评论让我发疯 :-) 我遇到了一个相关的问题,但代码在 MacOS 下运行良好,在 Windows 下运行不佳。 Shift 键事件不会在 MacOS 下生成,因此主要在该平台上编写的开发人员并不期望。由于“虚假”换档键事件,Windows 实现被破坏。【参考方案2】:

例如

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ListDemo extends JPanel 

    private static final long serialVersionUID = 1L;
    private JFrame frame = new JFrame("ListDemo");
    private JList list;
    private DefaultListModel listModel;

    public ListDemo() 
        super(new BorderLayout());
        listModel = new DefaultListModel();
        listModel.addElement("Jane Doe");
        listModel.addElement("John Smith");
        listModel.addElement("Kathy Green");
        list = new JList(listModel);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.setSelectedIndex(0);
        list.setVisibleRowCount(5);
        JScrollPane listScrollPane = new JScrollPane(list);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(listScrollPane, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
        setKeyBindings();
    

    private void setKeyBindings() 
        list.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
                .put(KeyStroke.getKeyStroke("DELETE"), "clickDelete");
        list.getActionMap().put("clickDelete", new AbstractAction() 

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) 
                int index = list.getSelectedIndex();
                if (index > -1) 
                    listModel.remove(index);
                
            
        );
    

    public static void main(String[] args) 
        javax.swing.SwingUtilities.invokeLater(new Runnable() 

            public void run() 
                ListDemo listDemo = new ListDemo();
            
        );
    

【讨论】:

我发现我浪费了太多时间可能是因为您的代码又不是 sscce。 SCNR :-) 在更严重的情况下:不要使用 ComponentInputMap(这是 WHEN_IN_FOCUSED_WINDOW 类型的一种),除非绝对必要,否则很难获得足够独特的此类绑定,并且它们始终是最后一个看见。相反,使用最近的父母的 WHEN_ANCESTOR 注册绑定,这是有意义的,这里是 f.i.内容窗格 @kleopatra 同意,但这是限制 KeyStroke DELETE 的原因,仅当 JList 在窗口中有焦点时 :-) 也许是我的肮脏黑客,也许是我的非_****,因为可能放这个监听器直接指向 JList .... 仅当 JList 有焦点时 如果这是您的意图,则绑定是完全错误的 - 使用 WHEN_FOCUSED 类型的列表的 inputMap - 显然与 OP 具​​有相同的焦点相关问题在 keyListener ;-) @kleopatra 请查看我的编辑,这是我了解KeyBindings 工作原理的方式,我感谢您的宝贵信息,但无法测试ANCESTOR 和@987654324 之间的差异和触发事件@现在

以上是关于Windows 和 Mac 在密钥检测方面的 Java 差异的主要内容,如果未能解决你的问题,请参考以下文章

sshd 的 Windows 10 OpenSSH 授权密钥错误

Parallels Desktop 12激活密钥+完整版免费下载

C/C++/Assembly 以编程方式检测超线程在 Windows、Mac 和 Linux 上是不是处于活动状态 [重复]

在 Javascript 中检测类似 Windows 或类似 Mac 的键盘

为 Mac 生成特定于机器的密钥

office for mac2019怎么用密钥