awt - chooser - Aplicación JavaFX en la bandeja del sistema
javafx stage filechooser (3)
Estoy creando una aplicación simple utilizando la interfaz de usuario JavaFX, la aplicación simplemente hace eso:
- tiene un icono de la bandeja del sistema, que cuando se hace clic muestra una ventana, cuando se hace clic nuevamente la oculta, en el botón derecho muestra un menú con 1 elemento "salir"
Ya hice la interfaz de usuario y coloqué la aplicación en la bandeja del sistema, pero no puedo mostrarla / ocultarla usando el método de Actionlistener normal, pero recibí este error:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = AWT-EventQueue-0
Aquí está el Código:
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionListener;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Main extends Application{
public static void main(String[] args) {
launch(args);
}
@Override
public void start(final Stage primaryStage) {
primaryStage.setTitle("Hello World!");
Button btn = new Button();
btn.setText("Say ''Hello World''");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Hello World!"); }
});
StackPane root = new StackPane();
root.getChildren().add(btn);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
if (SystemTray.isSupported()) {
SystemTray tray = SystemTray.getSystemTray();
Image image = Toolkit.getDefaultToolkit().getImage("Germany-politcal-map.jpg");
PopupMenu popup = new PopupMenu();
MenuItem item = new MenuItem("Exit");
popup.add(item);
TrayIcon trayIcon = new TrayIcon(image, "Amr_Trial", popup);
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent arg0) {
// TODO Auto-generated method stub
System.exit(0);
}
};
ActionListener listenerTray = new ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent arg0) {
// TODO Auto-generated method stub
primaryStage.hide();
}
};
trayIcon.addActionListener(listenerTray);
item.addActionListener(listener);
try{
tray.add(trayIcon);
}catch (Exception e) {
System.err.println("Can''t add to tray");
}
} else {
System.err.println("Tray unavailable");
}
//
}
}
Envuelva el código en el ActionListener que vuelve a llamar a JavaFX en Platform.runLater . Esto ejecutará el código que interactúa con el sistema JavaFX en el subproceso de la aplicación JavaFX en lugar de intentar hacerlo en el subproceso del evento Swing (que es lo que le causa problemas).
Por ejemplo:
ActionListener listenerTray = new ActionListener() {
@Override public void actionPerformed(java.awt.event.ActionEvent event) {
Platform.runLater(new Runnable() {
@Override public void run() {
primaryStage.hide();
}
});
}
};
Por defecto, la aplicación se cerrará cuando la última ventana esté oculta . Para anular este comportamiento predeterminado, invoque Platform.setImplicitExit(false) antes de mostrar la primera etapa de la aplicación. Luego deberá llamar explícitamente a Platform.exit() cuando necesite que la aplicación se apague realmente.
Creé una demostración para usar la bandeja del sistema AWT dentro de una aplicación JavaFX .
La bandeja del sistema no es compatible con JavaFX todavía. Puede hacer un seguimiento del progreso de esta tarea bajo el siguiente problema de JIRA: https://bugs.openjdk.java.net/browse/JDK-8090475
El problema también proporciona una solución alternativa, que podría utilizarse en JavaFX 8 para obtener el soporte básico.
La función no está planificada para JavaFX 8, por lo que podría lanzarse en una de las siguientes actualizaciones o incluso en JavaFX 9.
Solo debe modificar las clases javafx en el hilo javafx, es probable que los oyentes en el icono de la bandeja se ejecuten en el hilo de swing. Puede hacer esto publicando un runnable en Platform # runLater de la siguiente manera:
Platform.runLater(new Runnable() {
public void run() {
primaryStage.hide();
}
});