Comment arrêter "JavaFX application Thread"

j'ai une application de console simple qui a parfois besoin d'effectuer des opérations graphiques, pour ceux que J'utilise JavaFx framework (il y a certaines fonctions dont j'ai besoin comme le style css pour le texte ) Je génère simplement des formes et du texte dans une scène cachée, puis je les enregistre dans un fichier et c'est tout,

je sais que pour travailler avec JavaFx je dois passer les opérations graphiques au thread JavaFx, mais quand tout est fait et que je dois fermer l'application (après quelques heures) ce fil JavaFx reste ouvert... et je ne veux vraiment pas forcer la sortie avec le système.exit () parce que si quelque chose est bloqué je voudrais savoir/attendre (aussi je ne veux pas exécuter tout comme une application JavaFx (comme les composants JavaFx sont moins de 1% de mon application principale)

le code est très simple et googler autour de j'ai trouvé seulement à utiliser

Platform.exit();

ce qui ne semble pas fonctionner, j'ai aussi essayé de jouer avec les paramètres de la plateforme comme

Platform.setImplicitExit(false);

voici mon application test que vous pouvez exécuter:

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.geometry.Pos;
import javafx.scene.layout.VBox;

public class SOTestFX {
    public static void main(String[] args) {
        SOTestFX t = new SOTestFX();
        t.runFxThread();
    }

    public  void runFxThread(){
        //Application.launch(args);
        final JFXPanel jfxPanel = new JFXPanel(); 
        Platform.runLater(new Runnable() {
            @Override
            public void run() {

                System.err.println("CREATING IMAGE");
                simpleFXoperations();
                System.err.println("NOW CALL EXIT");
                System.err.println("JAVA FX THREAD SHOULD BE EXITED NOW");
                Platform.exit();
            }
        });

        try {
            Thread.sleep(3000); // just wait a bit if something should happen, let it happen..
        } catch (InterruptedException e) {
            e.printStackTrace();  
        }
        //jfxPanel.removeNotify(); // return ->  java.lang.NullPointerException
        //Platform.exit(); // -> does nothing

        System.err.println("i will never die!");
    }
    public void simpleFXoperations(){

        VBox vbox1 = new VBox();
        vbox1.setAlignment(Pos.BOTTOM_CENTER);
        vbox1.setStyle("-fx-border-style: solid;"
                + "-fx-border-width: 1;"
                + "-fx-border-color: white");
        System.err.println("simpleFXoperations() _DONE");
    }
}

et c'est le thread qui n'a jamais fermer

"Joindre Auditeur" - Thread t@17 java.lang.Fil.État: RUNNABLE

Verrouillé ownable synchroniseurs: - Aucun

"JavaFX Application Thread" - Thread t@13 java.lang.Fil.État: RUNNABLE au com.soleil.verre.interface.gtk.GtkApplication._runLoop(Native La méthode) COM.soleil.verre.interface.gtk.GtkApplication$3$1.cours (GtkApplication.java: 82) à java.lang.Fil.run (Thread.java: 722)

Verrouillé ownable synchroniseurs: - Aucun

mise à Jour: j'utilise le dernier Oracle JDK 7u17 64bit sur Linux Fedora 16 64bit.

16
demandé sur artless noise 2013-04-04 13:58:51

4 réponses

Correction:

j'ai pu corriger ce problème en appelant com.sun.javafx.application.PlatformImpl.tkExit() juste avant Platform.exit(). Je ne comprends pas très bien la source JavaFX, mais elle semble fonctionner; YMMV.

mise à Jour: faire ceci en Java 8 va produire un avertissement, vous pouvez simplement désactiver l'avertissement avec @SuppressWarnings("restriction"). Il ne devrait pas être un problème.

Explication:

j'ai pensé que cela en fouillant dans le code source; JFXPanel a ce petit l'extrait de code (ce qui est de JavaFX 2.2.25)

finishListener = new PlatformImpl.FinishListener() {
  public void idle(boolean paramAnonymousBoolean) {
    if (!JFXPanel.firstPanelShown) {
      return;
    }
    PlatformImpl.removeListener(JFXPanel.finishListener);
    JFXPanel.access2(null);
    if (paramAnonymousBoolean)
      Platform.exit();
  }

  public void exitCalled()
  {
  }

le problème est que, si vous n'utilisez Qu'un petit peu de JavaFX dans votre application, alors le idle(boolean) la méthode ne fait jamais rien (parce que firstPanelShown == false), ce qui empêche L'auditeur de se faire enlever, ce qui empêche le JavaFX Toolkit arrêt... ce qui signifie que vous devez l'arrêter manuellement.

23
répondu durron597 2015-09-17 20:16:34

votre fonction principale n'appartient pas à L'objet D'Application JavaFx et je pense que votre programme n'a jamais mis en place de boucle de thread d'application.

Il semble que vous devriez faire:

public class SOTestFX extends Application {
    public static void main(String[] args) {
        launch(args);
    }
    @Override
    public void start(Stage stage) throws Exception {
        // Do stuff here to show your stage or whatever you want;
        // This will be called on the JavaFX thread
    }
}
2
répondu LeonidVlad 2013-04-12 06:47:52

c'est une situation glissante, car (à ma connaissance) le but du fil JavaFX est de tirer parti de divers pipelines matériels de manière transparente. Puis-je suggérer de placer vos requêtes JavaFX dans un projet séparé, référencé, et de garder tout le reste, y compris votre méthode principale, dans un autre? C'est toujours fonctionné pour moi.

fondamentalement, la logique et le modèle d'affaires vont dans un projet, et la vue et le contrôle (généralement basé sur JavaFX) vont dans l'autre. Cela permet de terminaison indépendante du fil JavaFX. Espérons que cela s'applique à ce que vous essayez de faire.

2
répondu Michael Oberlin 2013-09-04 11:39:30

j'ai essayé beaucoup de choses sur ce qu'aucune des réponses ci-dessus, a travaillé pour moi. La meilleure chose pour moi était de juste fermer toute la JVM en utilisant

System.exit(1);

comme toute mon Application est juste Qu'une application JavaFX et donc peut être arrêtée, lors de la fermeture de la scène. Le 1 dans mon cas est juste un int aléatoire.

1
répondu Wingie 2015-08-27 07:50:58