FX Preloader

Kababär

Top Contributor
Hi,

ich würde gerne einen Preloader zu meiner Applikation hinzufügen. Bis jetzt habe ich eine eigene GUI (FXML + fxml root controller) als Login-Dialog erstellt, bevor die primaryStage (durch start(Stage stage)) geladen wird.
Ziel ist es, ein Login-Dialog anzuzeigen. Waren die Eingaben gültig, werden Applikations-spezifische Komponenten erstellt und geladen und es werden weitere Prüfungen gemacht (Datenbank, XML-Dateien, erstelle Ordner für Applikationsdateien im home-Verzeichnis, etc...).
Fehler während der Initialisierung (Preloading) sollten Dialoge anzeigen und dann das Programm beenden. Falls alles korrekt verlaufen ist, soll die MainStage angezeigt werden.

Wie setzt man so etwas um?
 

dzim

Top Contributor
Das Problem mit dem Preloader ist: Um ihn zu starten, musst du eine Private API verwenden - das geht mit Java 8 noch ganz gut (auch wenn dir eine Warnung um die Ohren geworfen wird), aber ich weiss nicht, wie es mit Java 9 ist.

Java 8: https://blog.codecentric.de/en/2015/09/javafx-how-to-easily-implement-application-preloader-2/

Der Grund findet sich in der JavaDoc (Java 9) sogar wieder: http://docs.oracle.com/javase/9/docs/api/javafx/application/Preloader.html - es geht/ging eben speziell um "embedded in a browser". Du kannst also nun entweder bei Java 8 bleiben und Private APIs verwenden, oder aber deiner Stage ist erst einmal nur das Login-Fenster und startet, wenn der Login erfolgreich ist, einfach eine weitere Stage (a.k.a. ein weiteres Fenster) und schliesst sich dann. Oder aber, du konstruierst dir einen "lightweigt" Dialog, der ein semi-transparentes Frame über dein fertiges UI legt und nur verschwinden kann, wenn er erfolgreich ist.
Beispiel: JFoenix-Dialog - https://github.com/jfoenixadmin/JFo...main/java/com/jfoenix/controls/JFXDialog.java
Achtung: Dann aber den Hauptbereich "disablen", denn Focus Traversal (also mit Tab weiterschalten) geht immer noch!

Ich werde meinen Private-API-Preloader wohl auch bald mal so umschreiben dürfen...
 

Kababär

Top Contributor
Hi,

danke dzim für deine Antwort. Die Seiten, die du referenziert hast, habe ich mir ebenfalls schon angeguckt (außer JFoenix). Den Preloader finde ich an für sich nicht schlecht. Aber wo steht denn da was von private?
Ich habe hier was "cooles" gefunden, wo Oracle ein paar Beispiele mit Preloader macht und da ist sogar was dabei, das auf mich zugeschnitten ist (9.3.5):
http://docs.oracle.com/javafx/2/deployment/preloaders.htm#BABDDGCD


Preloader lassen sich durch den javapackager immer einbinden (in Nativen Bundles):

Das konnte ich auch feststellen, zumindest, dass es nicht immer funktioniert. Einen ProgressBar anzuzeigen geht, das Login Beispiel allerdings nicht.
Besonders schön finde ich das nicht...

meinen Private-API-Preloader
Wie war noch gleich der Link zu deinem Git-Repo? :D
 

dzim

Top Contributor
In meinem Git-Repo ist das nicht. Das verwende ich im Geschäft.
Die Lösung ist im wesentlichen der Lösung aus dem ersten Link (blog.codecentric.de) nachempfunden und verwenden die private API com.sun.javafx.application.LauncherImpl, weil nur über diese kann man unabhängig vom javapackager auch von der IDE aus den Preloader verwenden und ordentlich testen.

Was uns zu den privaten APIs bringt. Was ist das? Nun am einfachsten beschrieben, sind das alle Methoden (und Felder) die "restricted access" aufweisen.
Einfachstes Beispiel sind Methoden, die die z.B. nur über den Reflection-Mechanismus (wo man diese auch erst "accessible" machen muss) ansprechbar sind. Weiteres Beispiele sind JDK-Klassen (und deren Methoden), die in packages wie com.sun.* liegen. Zu guter letzt gibt es in JavaFX viele Methoden deren Name - entgegen der Konventionen mit dem Präfix impl_<methodenName> beginnen. All diese werden von den IDEs als "access restricted" erkannt, eine Warnung wird ausgegeben und im Fall von Java 9 stehen viele dieser APIs entweder gar nicht mehr zur Verfügung, oder sind explizit in Public-APIs umgewandelt worden.

Beispiel: com.sun.javafx.tk.Toolkit.getToolkit().enterNestedEventLoop(myLock) und com.sun.javafx.tk.Toolkit.getToolkit().exitNestedEventLoop(myLock, result) sind ab Java 9 so nicht mehr verfügbar und stattdessen gibt es hier Ersatz über die Klasse javafx.application.Platform mit statischen Methoden, die eine identische Signatur aufweisen.

Der Hintergrund ist, dass diese APIs nicht als stabil betrachtet werden dürfen. Es mag sein, dass sie über Jahre hinweg unverändert bleiben, sie können sich aber selbst nur mit einem Patch verändern oder entfernt werden.

Dein Beispiel übrigens bezieht sich im Wesentlichen auf Applets, wie an vielen Stellen zu entnehmen ist. Das kannst du also leider vergessen.

Noch ein Hinweis zu meinem Repo: Dort wirst du so ein Beispiel nicht finden. Auf Arbeit verwende ich in unser grossen Anwendung besagte Private-API und eine auf JavaFXPorts basierte Android-/iOS-App setzt auf einen Austausch auf beinahe oberster Ebene des Scene-Graphen (mein Root-Pane ist ein StackPane, dessen Children tausche ich hier aus).
Vielleicht sollte ich mal ein paar Beispiele machen... :)
 

Kababär

Top Contributor
Danke für die ausführliche Antwort.
All diese werden von den IDEs als "access restricted" erkannt, eine Warnung wird ausgegeben und im Fall von Java 9 stehen viele dieser APIs entweder gar nicht mehr zur Verfügung, oder sind explizit in Public-APIs umgewandelt worden.
Ich habe Java 9 noch nicht installiert. Ich verwende immer noch Version 1.8.0_121 (jdk) bzw. *_141 (jre).

Die oben genannten privaten Klassen habe ich noch nie gesehen, und auch noch nie gehört. Aber jetzt verwende ich den Preloader aus dem Blog, den du gepostet hattest.

Vielleicht sollte ich mal ein paar Beispiele machen...
Gerne, würde mich freuen :)
 

dzim

Top Contributor
Ich hab heute mal begonnen, da etwas aufzubauen. Wird aber sicher noch etwas dauern, bis ich damit durch bin.
 
Ähnliche Java Themen

Ähnliche Java Themen

Neue Themen


Oben