dorkbox / SystemTray

Cross-platform SystemTray support for Swing/AWT, macOS, GtkStatusIcon, and AppIndicator on Java 8+
Other
446 stars 58 forks source link

NPE when changing whole menu #193

Closed michal-devel closed 12 months ago

michal-devel commented 1 year ago

I have encountered NPE that causes shutdown when I try to change menu. Here's stacktrace:

Error shutting down EventDispatch
java.lang.NullPointerException: Cannot invoke "dorkbox.systemTray.peer.MenuPeer.add(dorkbox.systemTray.Menu, dorkbox.systemTray.Entry, int)" because "this.peer" is null
    at dorkbox.systemTray.Menu.lambda$add$0(Menu.java:242) ~[SystemTray-4.4.jar:2023-08-21T00:06:20.779247Z]
    at dorkbox.systemTray.util.EventDispatch.lambda$runLater$0(EventDispatch.java:67) ~[SystemTray-4.4.jar:2023-08-21T00:06:20.779247Z]
    at dorkbox.systemTray.util.EventDispatch.lambda$shutdown$1(EventDispatch.java:90) ~[SystemTray-4.4.jar:2023-08-21T00:06:20.779247Z]
    at dorkbox.systemTray.util.EventDispatch.lambda$runLater$0(EventDispatch.java:67) ~[SystemTray-4.4.jar:2023-08-21T00:06:20.779247Z]

Here's full code that causes NPE. You need to click menu and choose Turn OFF to get NPE.

public class SysTray {

   private final SystemTray systemTray;

   public SysTray() {
      this.systemTray = SystemTray.get("RunDictionary");

      systemTray.setStatus("Running");
      systemTray.setMenu(menuWhenOn());
   }

   private JMenu menuWhenOn() {
      final JMenu jMenu = new JMenu();

      final JMenuItem turnOffItem = new JMenuItem("Turn OFF");
      turnOffItem.addActionListener(e -> {
         final JMenu whenOff = menuWhenOff();
         changeState(whenOff);
      });

      final JMenuItem quitItem = new JMenuItem("Quit");
      quitItem.addActionListener(e -> {
         systemTray.shutdown();
         System.exit(0);
      });

      jMenu.add(turnOffItem);
      jMenu.add(quitItem);

      return jMenu;
   }

   private JMenu menuWhenOff() {
      final JMenu jMenu = new JMenu();

      final JMenuItem turnOnItem = new JMenuItem("Turn ON");
      turnOnItem.addActionListener(e -> {
         final JMenu whenOn = menuWhenOff();
         changeState(whenOn);
      });

      final JMenuItem quitItem = new JMenuItem("Quit");
      quitItem.addActionListener(e -> {
         systemTray.shutdown();
         System.exit(0);
      });

      jMenu.add(turnOnItem);
      jMenu.add(quitItem);

      return jMenu;
   }

   private void changeState(final JMenu menu) {
      systemTray.getMenu().remove();
      systemTray.setMenu(menu); // it seems that this line causes NPE
   }
}

Please let me know if you need more information. Cheers!

dorkbox commented 1 year ago

I’ll look into this. Thanks!

dorkbox commented 12 months ago

Fixed.