失去焦点时加速器命令不起作用

Posted

技术标签:

【中文标题】失去焦点时加速器命令不起作用【英文标题】:Accelerator commands not working when focus lost 【发布时间】:2016-09-20 08:04:08 【问题描述】:

我有以下swing 应用程序,

其中有一个自定义的JMenuBar

代码如下,

public class MenuBarTest 
    public static void main(String[] args) 
        new JFXPanel();
        final JFrame frame = new JFrame();
        frame.setLayout(new BorderLayout());
        frame.getContentPane().add(new JTextField("Testing", JLabel.CENTER),
                BorderLayout.CENTER);
        frame.setJMenuBar(new DummyMenuBar());
        frame.setSize(300, 300);
        frame.setVisible(true);
    

DummyMenuBar.java

public class DummyMenuBar extends JMenuBar 
private MenuBar menuBar;
private MenuItem menuItem;

public DummyMenuBar() 
    try 
        addToScene();
     catch (Exception e) 
    


private void addToScene() 
    final JFXPanel menuFxPanel = new JFXPanel();
    add(menuFxPanel);
    Platform.setImplicitExit(false);
    Platform.runLater(() -> 
        Scene scene = new Scene(new VBox(), 400, 20);
        initMenuItem();
        ((VBox) scene.getRoot()).getChildren().addAll(menuBar);
        menuFxPanel.setScene(scene);
    );


private void initMenuItem() 
    menuBar = new MenuBar();
    menuItem = new MenuItem("Item 1");
    menuItem.setAccelerator(new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN));
    Menu menu1 = new Menu("Dummy 1");
    menu1.getItems().add(menuItem);
    menuBar.getMenus().add(menu1);
    menuItem.setOnAction(new EventHandler<ActionEvent>() 
        @Override
        public void handle(ActionEvent event) 
            System.out.println(".handle()");
        
    );


问题是, accelerator 命令 (Ctrl+S) 仅在 Menubar 获得焦点时起作用。如果我点击JTextField(获得焦点)和加速器命令 不工作。

要让它再次工作,我必须再次点击MenuBar 以获得焦点。

我可以关联它,因为我在 JmenuBar(DummyMenuBar.java) 上添加了 JavaFX 项目,但不确定确切的根本原因。

我该如何解决这个问题?

【问题讨论】:

你检查过this @Madhan 是的,我已经尝试过了,如果焦点不在“JFXPanel”上,它仍然不起作用。由于“JFXPanel”扩展了“JComponent”,因此它希望焦点能够捕获关键事件。 【参考方案1】:

我使用KeyBinding 解决了问题,

public static void main(String[] args) 
        new JFXPanel();
        final JFrame frame = new JFrame();
        frame.setLayout(new BorderLayout());
        JTextField tf = new JTextField("Hello World");
        frame.getContentPane().add(tf,
                BorderLayout.CENTER);
        tf.getInputMap((JComponent.WHEN_FOCUSED)).put(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK), "Ctrl+S");
        tf.getActionMap().put("Ctrl+S", new SaveAction());
        frame.setJMenuBar(new DummyMenuBar());
        frame.setSize(300, 300);
        frame.setVisible(true);
    
        static class SaveAction extends AbstractAction 

        @Override
        public void actionPerformed(java.awt.event.ActionEvent e) 
            if((e.getSource() instanceof JTextField))
            System.out.println(".handle() in Action");
            
        
    

确保即使JFXPanel 失焦,加速器也能正常工作。

【讨论】:

以上是关于失去焦点时加速器命令不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Android 在 Vulkan 中失去焦点处理

引导模态焦点不起作用

EditText 请求焦点不起作用

在本机反应中单击 TextInput 字段外部时失去焦点并关闭键盘?

vue 2 - 输入时按钮@click不起作用:焦点随高度变化

我正在使用 Summernote。使用 Jquery focusout() 作为它的 div 但它不起作用