Prezados, boa tarde!
Faz tempo que não desenvolvo uma app JavaFx. Tenho que criar um systray que receberá mensagens de um serviço, via Socket. Essa parte está OK. O problema está no JFX.
Para facilitar a manutenção, pensei em organizar o código assim (só a estrutura relevante do JFX):
- meupackage
- menus
- ExitMenuItemHandler.java
- OtherMenuItemHandler.java
- SystrayMenuItem.java
- SystrayLauncher.java
Disso isso, um pouco de código…
SystrayLauncher.java
public class SystemTrayLauncher extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(final Stage mainStage) {
try {
Platform.setImplicitExit(false);
mainStage.initStyle(StageStyle.TRANSPARENT);
Toolkit.getDefaultToolkit();
if (SystemTray.isSupported()) {
SystemTray tray = SystemTray.getSystemTray();
PopupMenu menu = new PopupMenu();
SystrayMenuItems.createMenuItems(menu);
Image imageIcon = ImageIO.read(new URL(SystemConfiguration.SYSTEM_ICON));
TrayIcon icon = new TrayIcon(imageIcon, SystemConfiguration.SYSTEM_NAME, menu);
icon.addActionListener(event -> Platform.runLater(mainStage::hide));
tray.add(icon);
/** Start to listen to service **/
//not relevant
} else {
Alert dialog = new Alert(Alert.AlertType.ERROR);
dialog.setTitle(null);
dialog.setHeaderText("System tray unavailable! Click OK to finish application.");
Optional<ButtonType> result = dialog.showAndWait();
if (result.get() == ButtonType.OK) {
Platform.exit();
}
}
} catch (Exception exc) {
System.err.println(exc.getMessage());
}
}
}
No SystrayMenuItems eu apenas faço a inserção dos menuitems no popupmenu criado na SystrayLauncher
public static void createMenuItems(PopupMenu menu) {
menu.add(OtherMenuItemHandler.createMenuItem());
menu.addSeparator();
menu.add(ExitMenuItemHandler.createMenuItem());
}
E nos Handlers, apenas faço o ActionListener. Por exemplo, na ExitMenuItemHandler:
public static MenuItem createMenuItem() {
MenuItem exit = new MenuItem("Sair");
exit.addActionListener(event -> {
Alert dialog = new Alert(Alert.AlertType.CONFIRMATION);
dialog.setTitle("test");
dialog.setHeaderText("Confirm to exit application?");
Optional<ButtonType> result = dialog.showAndWait();
if (result.get() == ButtonType.OK) {
Platform.exit();
}
});
return exit;
}
O problema é que, quando eu clico no menu Sair, é exibido a exceção do título, no momento de exibir o Alert
: java.lang.IllegalStateException: Not on FX application thread;
Não sei bem como resolver o problema… Tentei já colocar todo o código das outras classes (SystrayMenuItems e ExitMenuItemHandler) na SystrayLauncher, mas também retorna o mesmo erro.
Como, nessa fase, não preciso de um Stage/Scene, o que devo fazer pra funcionar?
Obrigado antecipadamente!