gpt4 book ai didi

java - JMenuItem 和 ENTER 键释放

转载 作者:行者123 更新时间:2023-11-30 11:06:22 27 4
gpt4 key购买 nike

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

该项目的功能包含要打开的 JDialog。此对话框监听释放的 ENTER 键并在释放 ENTER 时启动其自身的功能。

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

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

如何解决这个问题?

如果解释有点困惑,可以这样总结:

I want a JMenuItem to receive ENTER-key-released-events and react to it, I do not want it to react to ENTER-key-pressed-events.

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

编辑

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 键释放事件之前,在新打开的对话框中强制执行 ENTER 键按下事件。

关于java - JMenuItem 和 ENTER 键释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29340121/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com