首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >系统托盘中的JavaFX应用程序

系统托盘中的JavaFX应用程序
EN

Stack Overflow用户
提问于 2012-09-25 03:13:17
回答 5查看 14.7K关注 0票数 20

我正在使用JavaFX UI制作一个简单的应用程序,这个应用程序只是简单地做到这一点:

  • 有一个系统托盘图标,单击时会显示一个窗口,再次单击时会将其隐藏,右键单击时会显示一个带有1个"exit“项的菜单

我已经制作了UI并将应用程序放到了系统托盘中,但是我不能使用普通的Actionlistener方法来显示/隐藏它,但我得到了这个错误:

代码语言:javascript
运行
复制
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = AWT-EventQueue-0

代码如下:

代码语言:javascript
运行
复制
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");
          } 
        //
    }
}
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-09-25 03:52:11

将代码包装在actionListener中,它在Platform.runLater中回调JavaFX。这将在JavaFX应用程序线程上执行与JavaFX系统交互的代码,而不是尝试在Swing事件线程上执行(这就是导致问题的原因)。

例如:

代码语言:javascript
运行
复制
ActionListener listenerTray = new ActionListener() {                
  @Override public void actionPerformed(java.awt.event.ActionEvent event) {
    Platform.runLater(new Runnable() {
      @Override public void run() {
        primaryStage.hide();
      }
    });
  }                   
};            

默认情况下,应用程序将使用shutdown when it's last window is hidden。要覆盖此默认行为,请在显示第一个应用程序阶段之前调用Platform.setImplicitExit(false)。然后,当您需要应用程序真正关闭时,您将需要显式调用Platform.exit()

我创建了一个demo for using the AWT system tray within a JavaFX application

票数 22
EN

Stack Overflow用户

发布于 2012-09-25 03:50:39

您应该只修改javafx线程上的javafx类,托盘图标上的侦听器很可能在swing线程上运行。您可以通过将runnable发布到Platform#runLater来完成此操作,如下所示:

代码语言:javascript
运行
复制
Platform.runLater(new Runnable() {
    public void run() {
        primaryStage.hide();
    }
});
票数 4
EN

Stack Overflow用户

发布于 2013-09-01 18:24:14

JavaFX尚不支持系统托盘。您可以在以下JIRA问题下跟踪此任务的进度:https://bugs.openjdk.java.net/browse/JDK-8090475

该问题还提供了一种解决方法,可以在JavaFX 8中使用它来获得基本支持。

该功能并未计划在JavaFX 8中使用,因此它可能会在以下更新之一中发布,甚至会在JavaFX 9中发布。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12571329

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档