2012-09-24 15 views
16

Robię prosta aplikacja za pomocą JavaFX UI, aplikacja po prostu zrób to:JavaFX aplikacji w zasobniku systemowym

  • ma ikonkę w zasobniku, który po kliknięciu wyświetla się okno po kliknięciu ponownie ukrywa go na rightclick pokazuje menu z 1 "wyjściem" pozycja

Już zrobiłem UI i umieścić aplikację w Sys Tray, ale nie mogę pokazać/ukryć go za pomocą metody Normal Actionlistener, ale mam ten błąd:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = AWT-EventQueue-0 

Oto kod:

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"); 
      } 
     // 
    } 
} 

Odpowiedz

19

owijane kod w ActionListener który oddzwania do JavaFX w Platform.runLater. Spowoduje to wykonanie kodu, który łączy się z systemem JavaFX w wątku aplikacji JavaFX, zamiast próbować go wykonać w wątku zdarzenia Swing (co jest przyczyną problemów).

Na przykład:

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

Domyślnie aplikacja shutdown when it's last window is hidden. Aby zastąpić to domyślne zachowanie, wywołaj Platform.setImplicitExit(false) przed wyświetleniem pierwszego etapu aplikacji. Będziesz wtedy musiał jawnie zadzwonić pod numer Platform.exit(), kiedy naprawdę chcesz zamknąć aplikację.


Stworzyłem demo for using the AWT system tray within a JavaFX application.

+0

Tak, po prostu okazało się, że na stronie Dokumentacji, thx dużo. Ale kiedy to ukryję, nie pojawia się ponownie, nawet jeśli używam programu show() – amrlab

+0

Zaktualizowana odpowiedź, aby wyjaśnić ukryte/jawne zachowanie wyjścia. – jewelsea

+0

naprawdę, Thx dużo, i szukałem dużo dla tego !! – amrlab

4

Należy zmodyfikować tylko klas JavaFX na gwincie javafx, słuchacze na ikonę w zasobniku mogą być uruchomione na gwincie huśtawka. Można to zrobić poprzez umieszczenie runnable na platformę # runLater tak:

Platform.runLater(new Runnable() { 
    public void run() { 
     primaryStage.hide(); 
    } 
}); 
1

Zasobnik systemowy nie jest jeszcze obsługiwany w JavaFX. Możesz śledzić postępy w tym zadaniu w następującym wydaniu JIRA: https://bugs.openjdk.java.net/browse/JDK-8090475
Problem ten zapewnia obejście, które można zastosować w JavaFX 8, aby uzyskać podstawowe wsparcie.

Funkcja nie jest planowana dla JavaFX 8, więc to może być wydany w jednym z następujących aktualizacji lub nawet w JavaFX 9.

+4

Byłoby miło zobaczyć zawartość jiry bez rejestracji. – aphex

+1

Śledzenie funkcji znajduje się teraz na: https://bugs.openjdk.java.net/browse/JDK-8092115 –

Powiązane problemy