Faut le temps que ca se fasse aussi
J'ai note divers trucs un space note au cour de ces deux derniers jours passe a porter le script de démarrage de mon applis. Sachant que ce script se chargeait de tests et vérifications AVANT de lancer l'app principale (que je n'ai pas encore commence a porter) : durant le lancement des tests simples etaient initialement faits (version Java, JavaFX), puis un XDialog (voir JFXtras) affichait un logo de chargement, tandis que d'autres tests plus avances avaient lieu (RAM, espace disque, intégrité de l'install disque) et enfin la fenêtre de l'application principale se lançait. Pour finir le logo de chargement s’effaçait. J'avais donc besoin d'avoir une fenêtre flottante/dialogue AVANT le chargement de la fenêtre principale.
La gestion des threads est désormais importante, ainsi :
Il n'est plus question de lancer directement un stage depuis la thread courante non-EDT
Code :
static void test1() {
Stage stage = new Stage();
stage.setVisible(true);
}
donne :
Code :
Sélectionner tout - Visualiser dans une fenêtre à part
Exception in thread "main" java.lang.IllegalStateException: Not on FX application thread; currentThread = main
Normal c'est ce qu'on en attend.
Cependant ceci ne fonctionne pas non plus:
Code :
Sélectionner tout - Visualiser dans une fenêtre à part
static void test2() {
Platform.runLater(new Runnable() {
/**
* {@inheritDoc}
*/
@Override
public void run() {
Stage stage = new Stage();
stage.setVisible(true);
}
});
}
Code :
Sélectionner tout - Visualiser dans une fenêtre à part
Exception in thread "main" java.lang.IllegalStateException: Toolkit not initialized
En effet il manque l'appel a l'initialisation des runtimes... appel que je n'ai pas trouve dans l'API,
En fait cet appel est fait par la classe Application. (Ah mais son code n'est pas publique donc on ne sait pas ce qu'elle appelle...)
Ah ben oui c'est con-con mais il faut initialiser une Application AVANT de pouvoir afficher du JavaFX... ce qui explique en partie cette bizarrerie a la ligne 23 du didacticiel d’intégration de JavaFX 2.0 dans Swing (et le fait que leur classe étende Application).
Code :
Sélectionner tout - Visualiser dans une fenêtre à part
public class Main extends Application {
private static JFXPanel javafxPanel;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
initAndShowGUI();
}
});
}
public static void initAndShowGUI() {
JFrame frame = new JFrame("Swing application");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create JavaFX panel.
javafxPanel = new JFXPanel();
javafxPanel.setPreferredSize(new Dimension(550,400));
frame.getContentPane().add(javafxPanel, BorderLayout.CENTER);
// Create JavaFX scene.
Application.launch (Main.class, null);
// Show frame.
frame.pack();
frame.setVisible(true);
}
@Override
public void start (Stage mainStage) {
//Create the scene and the stage
Group root = new Group();
Scene scene = new Scene(root);
root.getChildren().add(createJavaFXContent());
// Add scene to panel
javafxPanel.setScene(scene);
}
}
Ce qui fait qu'on se retrouve toujours avec un Stage qui ne sert a rien même si on ne l'affiche pas. C'est un peu bête je vais devoir faire que mon script de démarrage etende Application alors que je souhaitais plutôt découpler les choses...
Tien pendant qu'on en est a la classe Application, la méthode Application.launch(Class<? extends Application>, String[] args) prend en paramètres les arguments de la ligne de commande mais ces derniers ne sont jamais passe au constructeur de la classe (j'ai essaye divers variantes avec ou sans paramètre, seul le constructeur sans est instancie) et il n'est pas possible non-plus de les récupérer via l'API d'Application.
Pour le moment je passe par un membre statique, c'est un peu sale.
Niveau boite de dialogues c'est pas encore ça :
Alert a disparu, il va falloir revoir toute la messagerie plus profond dans l'appli.
Je n'arrive pas a utiliser PopupWindow ou Popup. Dans le meilleur des cas rien ne se passe/s'affiche, tandis que si je rend le mainStage (voir ci-dessus) visible et que j'y attache le popup, j'ai une exception... bref je sens qu'il va me falloir attendre le retour de XDialog...
Contrairement a ce qui était annoncé dans leur lettre d'intention initiale, point de boites de dialogues courantes (messages, filechooser, colorchooser, etc.) standards a l'horizon.
Autre:
Mon ordi du boulot a un sacre problème car des fois les pilotes graphiques plantent ou alors NetBeans ou JavaFX sont super ultra-lents.
Le pattern builder c'est bien sauf quand NetBeans vient foutre le bordel lors d'un formatage ce qui fait qu'on se retrouve avec une ligne d'initialisation de 3Km de long au lieu des appels bien agences les uns sous les autres.
Ainsi :
Code :
Sélectionner tout - Visualiser dans une fenêtre à part
final Stage splashScreen = new StageBuilder()
.title(MessageFormat.format(i18n.getString("SPLASH_SCREEN_TITLE"), PROG_NAME))
.width(image.getWidth() + 2 * margin)
.height(image.getHeight() + 2 * margin)
.style(StageStyle.TRANSPARENT)
.build();
devient grace a la "magie" de NetBeans :
Code :
Sélectionner tout - Visualiser dans une fenêtre à part
final Stage splashScreen = new StageBuilder().title(MessageFormat.format(i18n.getString("SPLASH_SCREEN_TITLE"), PROG_NAME)).width(image.getWidth() + 2 * 7).height(image.getHeight() + 2 * 7).style(StageStyle.TRANSPARENT).build();
Bref, c'est pas la joie (et encore j'ai choisi un exemple court). Bref il va falloir rendre un peu moins strictes les regles de formattage de NetBeans.
Le pattern builder + netbeans + la nouvelle gestion des evenements ca rend le codage des animations assez moches...
Code :
SequentialTransition launchAnimation = new SequentialTransitionBuilder().children(
// Make the splashscreen appear & start the app.
new FadeTransitionBuilder().duration(Duration.valueOf(2000)).node(splashView).toValue(1).onFinished(new EventHandler<ActionEvent>() {
/**
* {@inheritDoc}
*/
@Override
public void handle(ActionEvent event) {
startXXX(argsMap);
}
}).build(),
// Wait for 5s.
new PauseTransitionBuilder().duration(Duration.valueOf(5000)).build(),
// Make the splashscreen disapear and close it.
new FadeTransitionBuilder().duration(Duration.valueOf(2000)).node(splashView).toValue(0).onFinished(new EventHandler<ActionEvent>() {
/**
* {@inheritDoc}
*/
@Override
public void handle(ActionEvent event) {
splashScreen.close();
}
}).build()).build();
La aussi j'ai mis un exemple court...
Ca manque toujours autant de convertisseur AWT/Java2D <-> JavaFX pour les types de base (font, color).
La gestion du stoke reste basique comme pour 1.x (assez limite par rapport a Java 2D) mais il y ont intégré le positionnement relatif du stroke demande par Jim Weaver.
Ceci dit, c'est une version bêta et on est loin de la sortie donc je suis encore totalement confiant
Prochaines étapes pour dans les semaines a venir:
Créer un nœud/contrôle custom avec support CSS.
Intégrer du Swing dans JavaFX... j'ai divers idees la-dessus : pour certains types de composants (ceux dont justement j'ai besoin), je pense qu'il doit être possible de le rendre dans une BufferedImage empaquetée* dans une Image FX (quitte a mettre un timer pour faire des rafraichissements) et de forwarder des faux événements souris/clavier au composant Swing. Évidement ça ne marchera pas pour tous les composants (par exemples les composants a popup style JComboBox) mais pour le composant GIS dont j'ai besoin ça peut éventuellement fonctionner...
Partager