I want to be notified when my JPopupMenu
is hidden — whether because an item was selected, the menu was dismissed, or setVisible(false)
was called on it. Here is my test code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class A extends ComponentAdapter implements Runnable, ActionListener {
private JButton b;
public static void main(String[] args) {
EventQueue.invokeLater(new A());
}
public void run() {
JFrame f = new JFrame("Test");
b = new JButton("Click me");
b.addActionListener(this);
f.add(b);
f.pack();
f.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
JPopupMenu pm = new JPopupMenu();
pm.addComponentListener(this);
pm.add("Popup...");
pm.add("...menu!");
pm.show(b, 10, 10);
}
public void componentShown(ComponentEvent e) { System.out.println("componentShown"); }
public void componentHidden(ComponentEvent e) { System.out.println("componentHidden"); }
}
Regardless of how I interact with the menu, neither of the two ComponentListener
methods are being called. Why is that? Is there different/better/correct way of finding out when my JPopupMenu
is hidden?
Thanks,
Cameron
JPopupMenu
has a special listener for visibility change events:
pm.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
System.out.println("cancelled");
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
System.out.println("vanishing");
}
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
System.out.println("appearing");
}
});
Note, however, as method names hint, they are called before visibility changes, so if you're calling isVisible()
somewhere in the event handlers, you should be aware of that, for example:
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
updateMenu();
}
private void updateMenu() {
if (!menu.isVisible()) { // this won't work!
// perform some updates
}
}
With regards to why ComponentListener
isn't sending you events on the menu disappearing, this might explain:
The component-hidden and component-shown events occur only as the result of calls to a Component 's setVisible method. For example, a window might be miniaturized into an icon (iconified) without a component-hidden event being fired.
Source: ComponentListener tutorial (non-canonical perhaps, but from the horse's mouth.)
Consider that in conjunction with JPopupMenu
's implementation of setVisible
:
public void setVisible(boolean b) {
// Not supported for MenuComponents
}
And you might know how it so happens, but not why it happens (what is the justification and where is that properly documented?)