Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JMenuItem并输入键released_Java_Swing_Keyboard Events_Jmenuitem_Keyrelease - Fatal编程技术网

Java JMenuItem并输入键released

Java JMenuItem并输入键released,java,swing,keyboard-events,jmenuitem,keyrelease,Java,Swing,Keyboard Events,Jmenuitem,Keyrelease,我有一个JMenuItem,我想接收用户输入。用户必须能够通过鼠标或键盘启动项目的功能 该项的功能包含要打开的JDialog。此对话框将侦听已释放的ENTER键,并在释放ENTER键时启动自己的功能 当用户使用ENTER(按键)点击JMenuItem时,他将打开对话框。当他放开回车键时,他将-这就是问题所在--导致对话框功能启动。(当用户松开ENTER键时,他将向现在打开的JDialog触发一个事件。我不想这样。我想要两个单独的步骤:1:使用ENTER(完成笔划或ENTER释放)选择JMenuI

我有一个
JMenuItem
,我想接收用户输入。用户必须能够通过鼠标或键盘启动项目的功能


该项的功能包含要打开的
JDialog
。此对话框将侦听已释放的ENTER键,并在释放ENTER键时启动自己的功能

当用户使用ENTER(按键)点击
JMenuItem
时,他将打开对话框。当他放开回车键时,他将-这就是问题所在--导致对话框功能启动。(当用户松开ENTER键时,他将向现在打开的
JDialog
触发一个事件。我不想这样。我想要两个单独的步骤:1:使用ENTER(完成笔划或ENTER释放)选择
JMenuItem
,2:使用ENTER(完成笔划或ENTER释放)在JDialog中启动新功能

到目前为止,我已经尝试了几种方法,但我无法让
JMenuItem
接收关键发布事件。这似乎是一些我目前无法解决的焦点问题

如何解决这个问题

如果解释有点混乱,可以总结如下:

我希望一个
JMenuItem
接收ENTER键释放事件并对其作出反应,我不希望它对ENTER键按下事件作出反应

一个小的代码示例可能会显示我的问题:

编辑

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRootPane;
import javax.swing.KeyStroke;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;

public class MenuItemProblem {
    public static void openDialog(JFrame frame){
        Action enterReleasedAction = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // This action shall be triggered by releasing
                // the enter key in the JDialog.
                // (There are two times events of the released enter key shall be
                // evaluated during the application runs, of which this is the second one.)
                // But: It is triggered by the first release of enter in the application,
                // which is the one to choose the menu item.
                System.out.println("Dialog: Enter was released!");
            }
        };
        JDialog dialog = new JDialog(frame, "My dialog", true);
        JRootPane rootPane = dialog.getRootPane();
        ActionMap actionMap = rootPane.getActionMap();
        String enterReleased = "my_enter_released_function";
        actionMap.put(enterReleased, enterReleasedAction);
        InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);    
        // Keystroke for releasing the enter key
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), enterReleased);

        dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        dialog.setMinimumSize(new Dimension(260, 300));
        dialog.setResizable(true);
        dialog.pack();
        dialog.setLocationRelativeTo(frame);
        dialog.setVisible(true);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("My App");
        JMenuItem item = new JMenuItem("My item");
        item.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // By releasing enter (and mouse clicks, space and so on)
                // this action shall be triggered.
                // It shall not be triggered by enter key pressed,
                // for this would cause the action of the called dialog
                // do be triggered.
                // But: It is triggered by enter pressed!
                // (There are two times events of the released enter key shall be
                // evaluated during the application runs, of which this is the first one.)
                System.out.println("Choosing the menu item");
                openDialog(frame);
            }
        });

        JMenu menu = new JMenu("My menu");
        menu.add(item);
        JMenuBar bar = new JMenuBar();
        bar.add(menu);

        // Register alt key to be caught
        Action altAction = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                MenuElement[] elements = MenuSelectionManager.defaultManager().getSelectedPath();
                if(elements.length > 0){
                    MenuSelectionManager.defaultManager().clearSelectedPath();
                } else{
                    menu.doClick();
                }
            }
        };
        JRootPane rootPane = frame.getRootPane();
        ActionMap actionMap = rootPane.getActionMap();
        String altActionKey = "alt_key_for_menu";
        actionMap.put(altActionKey, altAction);
        InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_ALT, 0, true);
        inputMap.put(ks, altActionKey);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setJMenuBar(bar);
        frame.setSize(350, 250);
        frame.setVisible(true);
    }
}
是的,如果你们能给我指出正确的方向,我会很高兴的。
提前感谢并感谢您的努力!

好的,问题解决了。我没有尝试调整API,而是调整了对话框功能的触发方式。详细地说,我将触发器从ENTER released更改为ENTER typed。一些示例代码了解了我所做的工作:

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRootPane;
import javax.swing.KeyStroke;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;

public class MenuItemSolution {
    public static void openDialog(JFrame frame){
        Action enterTypedAction = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Dialog: Enter was typed!");
            }
        };
        JDialog dialog = new JDialog(frame, "My dialog", true);
        JRootPane rootPane = dialog.getRootPane();
        ActionMap actionMap = rootPane.getActionMap();
        String enterTyped = "my_enter_typed_function";
        actionMap.put(enterTyped, enterTypedAction);
        InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);    
        // This is the point of change: I just created a KeyStroke to
        // deal with ENTER key typed instead of ENTER key released.
        // Only problem left (which doesn't matter in my use case):
        // Key typed events can occur several time when holding down the ENTER key.
        inputMap.put(KeyStroke.getKeyStroke('\n'), enterTyped);
        dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        dialog.setMinimumSize(new Dimension(260, 300));
        dialog.setResizable(true);
        dialog.pack();
        dialog.setLocationRelativeTo(frame);
        dialog.setVisible(true);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("My App");
        JMenuItem item = new JMenuItem("My item");
        item.addActionListener((ActionEvent e) -> {
            openDialog(frame);
        });
        JMenu menu = new JMenu("My menu");
        menu.add(item);
        JMenuBar bar = new JMenuBar();
        bar.add(menu);

        // Register alt key to be caught
        Action altAction = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                MenuElement[] elements = MenuSelectionManager.defaultManager().getSelectedPath();
                if(elements.length > 0){
                    MenuSelectionManager.defaultManager().clearSelectedPath();
                } else{
                    menu.doClick();
                }
            }
        };
        JRootPane rootPane = frame.getRootPane();
        ActionMap actionMap = rootPane.getActionMap();
        String altActionKey = "alt_key_for_menu";
        actionMap.put(altActionKey, altAction);
        InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_ALT, 0, true);
        inputMap.put(ks, altActionKey);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setJMenuBar(bar);
        frame.setSize(350, 250);
        frame.setVisible(true);
    }
}
感谢大家的关注,特别是@MadProgrammer和@mKorbel

编辑

据我所知,还有一些更好的方法。
第一种方法:
设置计时器,以对新打开的对话框中输入的按键释放事件作出反应。
第二种方法:

在处理
ENTER
按键释放事件之前,在新打开的对话框中强制执行
ENTER
按键按下事件。

这不是默认情况下的工作方式吗?对于JMenuItem(对于JMenu,是否有其他侦听器))是否正确实现了默认值(如程序员所述),您可以使用MenuListener、MenuKeyListener和ButtonModel中的事件,这里缺少…看看助记符和加速器,该项的功能包含一个要打开的JDialog。此对话框侦听已释放的enter键。==我希望只有一个JDialog具有CardLayout@MadProgrammer:否,项目接收已按下的事件,但不接收released-event.No要点是,使用键盘打开一个
JMenu
,选择一个
JMenuItem
,按
Enter
将触发
JMenuItem
关联的
ActionListener
,所有这些额外的
KeyListener
东西只是增加了不需要的复杂性