title: Showing/hiding a JPopupMenu from a JButton; FocusListener not working?
body: <p>I needed a JButton with an attached dropdown style menu. So I took a JPopupMenu and attached it to the JButton in the way you can see in the code below. What it needs to do is this: </p>
  
  <ul>
  <li>show the popup when clicked</li>
  <li>hide it if clicked a second time</li>
  <li>hide it if an item is selected in the popup</li>
  <li>hide it if the user clicks somewhere else in the screen</li>
  </ul>
  
  <p>These 4 things work, but because of the boolean flag I'm using, if the user clicks somewhere else or selects an item, I have to click twice on the button before it shows up again. That's why I tried to add a FocusListener (which is absolutely not responding) to fix that and set the flag false in these cases.</p>
  
  <p><strong>EDIT: Last attempt in an answer post...</strong></p>
  
  <p>Here are the listeners: (It's in a class extending JButton, so the second listener is on the JButton.)</p>
  
  <pre><code>// 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;
    }
   }
  });
  </code></pre>
  
  <p>I've been fighting with this for way too long now. If someone can give me a clue about what's wrong with this, it would be great!</p>
  
  <p>Thanks!</p>
  
  <p><strong>Code:</strong></p>
  
  <pre><code>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, -1, c.getHeight());
                      isShowingPopup = true;
                  }
              }
          });
  
          // Skip when navigating with TAB.
          setFocusable(true); // Was false first and should be false in the end.
  
          menu.setFocusable(true);
      }
  
  }
  </code></pre>