20

私は JavaFX UI を使用してシンプルなアプリを作成しています。アプリは単にそれを行うだけです:

  • systray アイコンがあり、クリックするとウィンドウが表示され、もう一度クリックすると非表示になり、右クリックすると 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");
          } 
        //
    }
}
4

5 に答える 5

22

Platform.runLaterで JavaFX にコールバックする actionListener にコードをラップします。これにより、Swingイベントスレッドで実行しようとするのではなく、JavaFXアプリケーションスレッドでJavaFXシステムとインターフェースするコードが実行されます(これが問題の原因です)。

例えば:

ActionListener listenerTray = new ActionListener() {                
  @Override public void actionPerformed(java.awt.event.ActionEvent event) {
    Platform.runLater(new Runnable() {
      @Override public void run() {
        primaryStage.hide();
      }
    });
  }                   
};            

デフォルトでは、アプリケーションは最後のウィンドウが非表示になったときにシャットダウンします。このデフォルトの動作をオーバーライドするには、最初のアプリケーション Stage を表示する前にPlatform.setImplicitExit(false)を呼び出します。アプリケーションを実際にシャットダウンする必要がある場合は、Platform.exit()を明示的に呼び出す必要があります。


JavaFX アプリケーション内で AWT システム トレイを使用するためのデモを作成しました。

于 2012-09-24T19:52:11.387 に答える
4

javafx スレッドの javafx クラスのみを変更する必要があります。トレイ アイコンのリスナーは、swing スレッドで実行されている可能性があります。次のように、ランナブルを Platform#runLater に投稿することでこれを行うことができます。

Platform.runLater(new Runnable() {
    public void run() {
        primaryStage.hide();
    }
});
于 2012-09-24T19:50:39.403 に答える
1

システム トレイは、JavaFX ではまだサポートされていません。このタスクの進行状況は、次の JIRA の問題で追跡できます: https://bugs.openjdk.java.net/browse/JDK-8090475
この問題は、JavaFX 8 で基本的なサポートを得るために使用できる回避策も提供します。 .

この機能は JavaFX 8 では計画されていないため、次の更新のいずれか、または JavaFX 9 でリリースされる可能性があります。

于 2013-09-01T10:24:13.757 に答える