击键时关闭 JPopupMenu
Close JPopupMenu on Keystroke
我正在创建一个自动完成处理文本的工具 IDE,Java 的自定义版本。下面的class是弹出来呈现不同填写可能性的弹出菜单:
class Entry extends JPopupMenu implements KeyListener{
private JEditTextArea parent;
public Entry(String word, JEditTextArea _parent) {
super();
parent = _parent;
parent.add(this);
parent.addKeyListener(this);
add(word);
}
public void show(int x, int y) {
super.show(parent, x, y);
}
public void keyPressed(KeyEvent key) {
setVisible(false);
setEnabled(false);
}
public void keyReleased(KeyEvent key) {}
public void keyTyped(KeyEvent key) {}
}
父项是 JEditTextArea,afaik 与 swing 包中的 JTextArea 共享其大部分功能。单词参数只是开始输入的单词,作为稍后在代码中查找合适补全的模式。
问题是,一旦弹出窗口打开,它就会阻止进一步输入新字符,您必须按 ESC 手动关闭它。我试图让它成为一个 KeyListener 并让它在击键时关闭,但到目前为止没有成功。我还尝试让它在任何击键时打印一条简单消息,但无论我尝试什么,我都无法说服它对任何形式的键输入做出反应。有什么方法可以让它在输入的击键时关闭吗?
~奥卡加纳
我无法真正使用您提供的 class,因为缺少一些 class。所以我刚刚创建了这个最小的工作示例,我希望它能说明你的问题:
import javax.swing.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
//Creating elements
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JButton button = new JButton("click me!");
JPopupMenu menu = new JPopupMenu("Menu");
menu.add("A");
menu.add("B");
menu.add("C");
//Open menu on button-click
button.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
menu.show(button, button.getWidth()/2, button.getHeight()/2);
}
});
//Close menu on CTRL+X
frame.addKeyListener(new KeyListener(){
@Override
public void keyPressed(KeyEvent e) {
//See https://docs.oracle.com/javase/8/docs/api/javax/swing/JPopupMenu.html#setVisible-boolean-
//See https://docs.oracle.com/javase/8/docs/api/javax/swing/JPopupMenu.html#isVisible--
if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_X && menu.isVisible()) {
menu.setVisible(false);
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
});
//Putting everything together
panel.add(button);
frame.add(panel);
frame.setSize(300,300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
这不起作用,因为密钥侦听器已添加到 JFrame。当按下按钮并打开菜单时,菜单获得焦点,因此 keylistener 不起作用。
这个问题可以通过在代码中添加以下几行来解决:
//this is doing the trick
button.setFocusable(false);
menu.setFocusable(false);
如果您不想这样做,只想将 KeyListener 添加到 JPopupMenu,那么您可以这样做:
//Open menu on button-click
button.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
menu.show(button, button.getWidth()/2, button.getHeight()/2);
menu.requestFocus();
}
});
//Close menu on CTRL+X
menu.addKeyListener(new KeyListener(){
@Override
public void keyPressed(KeyEvent e) {
//See https://docs.oracle.com/javase/8/docs/api/javax/swing/JPopupMenu.html#setVisible-boolean-
//See https://docs.oracle.com/javase/8/docs/api/javax/swing/JPopupMenu.html#isVisible--
if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_X && menu.isVisible()) {
menu.setVisible(false);
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
});
这里的技巧是在菜单打开后将焦点设置在菜单上(在按钮的 actionlistener 中):
menu.requestFocus();
我正在创建一个自动完成处理文本的工具 IDE,Java 的自定义版本。下面的class是弹出来呈现不同填写可能性的弹出菜单:
class Entry extends JPopupMenu implements KeyListener{
private JEditTextArea parent;
public Entry(String word, JEditTextArea _parent) {
super();
parent = _parent;
parent.add(this);
parent.addKeyListener(this);
add(word);
}
public void show(int x, int y) {
super.show(parent, x, y);
}
public void keyPressed(KeyEvent key) {
setVisible(false);
setEnabled(false);
}
public void keyReleased(KeyEvent key) {}
public void keyTyped(KeyEvent key) {}
}
父项是 JEditTextArea,afaik 与 swing 包中的 JTextArea 共享其大部分功能。单词参数只是开始输入的单词,作为稍后在代码中查找合适补全的模式。
问题是,一旦弹出窗口打开,它就会阻止进一步输入新字符,您必须按 ESC 手动关闭它。我试图让它成为一个 KeyListener 并让它在击键时关闭,但到目前为止没有成功。我还尝试让它在任何击键时打印一条简单消息,但无论我尝试什么,我都无法说服它对任何形式的键输入做出反应。有什么方法可以让它在输入的击键时关闭吗?
~奥卡加纳
我无法真正使用您提供的 class,因为缺少一些 class。所以我刚刚创建了这个最小的工作示例,我希望它能说明你的问题:
import javax.swing.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
//Creating elements
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JButton button = new JButton("click me!");
JPopupMenu menu = new JPopupMenu("Menu");
menu.add("A");
menu.add("B");
menu.add("C");
//Open menu on button-click
button.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
menu.show(button, button.getWidth()/2, button.getHeight()/2);
}
});
//Close menu on CTRL+X
frame.addKeyListener(new KeyListener(){
@Override
public void keyPressed(KeyEvent e) {
//See https://docs.oracle.com/javase/8/docs/api/javax/swing/JPopupMenu.html#setVisible-boolean-
//See https://docs.oracle.com/javase/8/docs/api/javax/swing/JPopupMenu.html#isVisible--
if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_X && menu.isVisible()) {
menu.setVisible(false);
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
});
//Putting everything together
panel.add(button);
frame.add(panel);
frame.setSize(300,300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
这不起作用,因为密钥侦听器已添加到 JFrame。当按下按钮并打开菜单时,菜单获得焦点,因此 keylistener 不起作用。
这个问题可以通过在代码中添加以下几行来解决:
//this is doing the trick
button.setFocusable(false);
menu.setFocusable(false);
如果您不想这样做,只想将 KeyListener 添加到 JPopupMenu,那么您可以这样做:
//Open menu on button-click
button.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
menu.show(button, button.getWidth()/2, button.getHeight()/2);
menu.requestFocus();
}
});
//Close menu on CTRL+X
menu.addKeyListener(new KeyListener(){
@Override
public void keyPressed(KeyEvent e) {
//See https://docs.oracle.com/javase/8/docs/api/javax/swing/JPopupMenu.html#setVisible-boolean-
//See https://docs.oracle.com/javase/8/docs/api/javax/swing/JPopupMenu.html#isVisible--
if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_X && menu.isVisible()) {
menu.setVisible(false);
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
});
这里的技巧是在菜单打开后将焦点设置在菜单上(在按钮的 actionlistener 中):
menu.requestFocus();