2012-09-24 43 views
16

estoy haciendo una aplicación sencilla utilizando JavaFX interfaz de usuario, la aplicación simplemente hacer eso:JavaFX aplicación en la bandeja del sistema

  • tiene un icono de la bandeja del sistema, que cuando se hace clic muestra una ventana, cuando se hace clic de nuevo lo oculta, en rightclick muestra un menú con 1 "de salida" elemento

ya que hice la interfaz de usuario y puesto la aplicación en la bandeja Sys, pero no puedo mostrar/ocultar utilizando el método normal actionListener, pero me dio 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"); 
      } 
     // 
    } 
} 

Respuesta

19

ajustar el código en el actionListener que se pide de nuevo a JavaFX en Platform.runLater. Esto ejecutará el código que interactúa con el sistema JavaFX en el hilo de la aplicación JavaFX en lugar de tratar de hacerlo en el hilo de evento Swing (que es lo que está causando 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 shutdown when it's last window is hidden. Para anular este comportamiento predeterminado, invoque Platform.setImplicitExit(false) antes de mostrar la primera etapa de la aplicación. Luego deberá llamar explícitamente al Platform.exit() cuando necesite que la aplicación realmente se cierre.


Creé un demo for using the AWT system tray within a JavaFX application.

+0

Sí, acabo de encontrar que en la página de documentación, THX mucho. Pero cuando lo oculto, no aparece de nuevo incluso si uso show() – amrlab

+0

Respuesta actualizada para explicar el comportamiento de salida implícito/explícito. – jewelsea

+0

realmente, ¡mucho, he estado buscando mucho para esto! – amrlab

4

Sólo debe modificar las clases de JavaFX en el hilo javafx, los oyentes sobre el icono de la bandeja es probable que se ejecuta en el hilo swing. Esto se puede hacer mediante la publicación de un ejecutable a la plataforma # runLater así:

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

La bandeja del sistema aún no es compatible con JavaFX. Puede realizar un seguimiento del progreso en esta tarea en la siguiente cuestión de JIRA: https://bugs.openjdk.java.net/browse/JDK-8090475
El problema también proporciona una solución, que podría usarse en JavaFX 8 para obtener el soporte básico.

La función no está prevista para JavaFX 8, lo que podría ser lanzado en una de las siguientes actualizaciones o incluso en JavaFX 9.

+4

Sería bueno ver el contenido jira sin registrarse. – aphex

+1

El seguimiento de funciones ahora está en: https://bugs.openjdk.java.net/browse/JDK-8092115 –

Cuestiones relacionadas