我正在使用 JavaFX UI 制作一个简单的应用程序,该应用程序只需执行以下操作:
- 有一个系统托盘图标,单击时显示一个窗口,再次单击时隐藏它,右键单击时显示一个带有 1 个“退出”项的菜单
我已经制作了 UI 并将应用程序放入系统托盘中,但我无法使用普通 Actionlistener 方法显示/隐藏它,但我收到此错误:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = AWT-EventQueue-0
这是代码:
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");
}
//
}
}
将代码包装在 actionListener 中,该回调回调到 JavaFX平台.runLater http://docs.oracle.com/javafx/2/api/javafx/application/Platform.html#runLater%28java.lang.Runnable%29。这将在 JavaFX 应用程序线程上执行与 JavaFX 系统交互的代码,而不是尝试在 Swing 事件线程上执行此操作(这正是导致问题的原因)。
例如:
ActionListener listenerTray = new ActionListener() {
@Override public void actionPerformed(java.awt.event.ActionEvent event) {
Platform.runLater(new Runnable() {
@Override public void run() {
primaryStage.hide();
}
});
}
};
默认情况下,应用程序将当最后一个窗口隐藏时关闭 http://docs.oracle.com/javafx/2/api/javafx/application/Application.html。要覆盖此默认行为,请调用Platform.setImplicitExit(假) http://docs.oracle.com/javafx/2/api/javafx/application/Platform.html#setImplicitExit%28boolean%29在展示第一个应用程序阶段之前。然后您需要显式调用平台.exit() http://docs.oracle.com/javafx/2/api/javafx/application/Platform.html#exit%28%29当您需要应用程序真正关闭时。
我创建了一个在 JavaFX 应用程序中使用 AWT 系统托盘的演示 https://gist.github.com/jewelsea/e231e89e8d36ef4e5d8a.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)