>单击时显示弹出窗口
>如果再次点击,请隐藏它
>如果在弹出窗口中选择了某个项目,则将其隐藏
>如果用户点击屏幕中的其他位置,则隐藏它
这4件事情都有效,但由于我正在使用的布尔标志,如果用户点击其他地方或选择了一个项目,我必须在按钮上单击两次才会再次显示.这就是为什么我试图添加一个FocusListener(绝对没有响应)来修复它并在这些情况下将标志设置为false.
编辑:最后一次尝试回答帖子……
以下是监听器:(它在一个扩展JButton的类中,所以第二个监听器在JButton上.)
// Show popup on left click. menu.addFocusListener(new FocusListener() { @Override public void focusLost(FocusEvent e) { System.out.println("LOST FOCUS"); isShowingPopup = false; } @Override public void focusGained(FocusEvent e) { System.out.println("GAINED FOCUS"); } }); addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("isShowingPopup: " + isShowingPopup); if (isShowingPopup) { isShowingPopup = false; } else { Component c = (Component) e.getSource(); menu.show(c,-1,c.getHeight()); isShowingPopup = true; } } });
我现在已经用这个太久了.如果有人能给我一个关于这个问题的线索,那就太好了!
谢谢!
码:
public class Button extends JButton { // Icon. private static final ImageIcon ARROW_SOUTH = new ImageIcon("ArrowSouth.png"); // Unit popup menu. private final JPopupMenu menu; // Is the popup showing or not? private boolean isShowingPopup = false; public Button(int height) { super(ARROW_SOUTH); menu = new JPopupMenu(); // menu is populated somewhere else // FocusListener on the JPopupMenu menu.addFocusListener(new FocusListener() { @Override public void focusLost(FocusEvent e) { System.out.println("LOST FOCUS"); isShowingPopup = false; } @Override public void focusGained(FocusEvent e) { System.out.println("GAINED FOCUS"); } }); // ComponentListener on the JPopupMenu menu.addComponentListener(new ComponentListener() { @Override public void componentShown(ComponentEvent e) { System.out.println("SHOWN"); } @Override public void componentResized(ComponentEvent e) { System.out.println("RESIZED"); } @Override public void componentMoved(ComponentEvent e) { System.out.println("MOVED"); } @Override public void componentHidden(ComponentEvent e) { System.out.println("HIDDEN"); } }); // ActionListener on the JButton addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("isShowingPopup: " + isShowingPopup); if (isShowingPopup) { menu.requestFocus(); isShowingPopup = false; } else { Component c = (Component) e.getSource(); menu.show(c,c.getHeight()); isShowingPopup = true; } } }); // Skip when navigating with TAB. setFocusable(true); // Was false first and should be false in the end. menu.setFocusable(true); } }
解决方法
FocusListener必须如下:
menu.addFocusListener(new FocusListener() { @Override public void focusLost(FocusEvent e) { System.out.println("LOST FOCUS"); isShowingPopup = false; } @Override public void focusGained(FocusEvent e) { System.out.println("GAINED FOCUS"); isShowingPopup = true; } });
isShowingPopup布尔值在其他任何地方都不会改变 – 如果它获得焦点,它会假定它已经显示,如果它失去了焦点,它就会认为它没有.
接下来,按钮上的ActionListener是不同的:
addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("isShowingPopup: " + isShowingPopup); if (showPopup) { Component c = (Component) e.getSource(); menu.show(c,c.getHeight()); menu.requestFocus(); } else { showPopup = true; } } });
现在真的是新的一点.它是按钮上的MouseListener:
addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { System.out.println("ispopup?: " + isShowingPopup); if (isShowingPopup) { showPopup = false; } } @Override public void mouseReleased(MouseEvent e) { showPopup = true; } });
基本上,在菜单失去焦点之前会调用mousePressed,因此isShowingPopup反映了在按下按钮之前是否显示了弹出窗口.然后,如果菜单在那里,我们只是将showPopup设置为false,这样actionPerformed方法一旦被调用就不显示菜单(在放开鼠标之后).
这种情况在每种情况下都表现如预期但只有一种:如果显示菜单并且用户将鼠标按在按钮上但将其释放到其外部,则从未调用actionPerformed.这意味着showPopup仍为false,下次按下按钮时菜单未显示.要解决此问题,mouseReleased方法会重置showPopup.据我所知,在actionPerformed之后调用mouseReleased方法.
我玩了一下结果按钮,做了我能想到的所有按钮,它按预期工作.但是,我并非100%确定事件将始终以相同的顺序发生.
最终,我认为这至少值得尝试.