juillet
2013
J’ai commencé ces derniers temps à faire quelques essais avec le JDK8 même si je suis assez loin de passer tous mes devs sur cette version : il y a encore des bugs de rendu ici et là ; il y a seulement quelques versions le nœud racine d’une application ne se redimensionnait pas correctement avec la fenêtre ou encore les CSS s’appliquaient bizarrement. NetBeans 7.3 est loin de supporter la nouvelle syntaxe (apparemment le support des lambdas est prévu pour NetBeans 7.4) et il faut bidouiller les projets pour inclure les runtimes depuis le répertoire jre/lib/ext du JDK 8 sinon il ne les trouve pas et applique par défaut celles du JDK 7. Mais ça s’améliore de version en version.
Cette fois-ci j’ai décidé de tester une nouvelle fonctionnalité de JavaFX 8 : l’impression.
Pour rappel, dans JavaFX 2.0 et 2.1 on ne pouvait pas mais alors pas du tout exporter ou imprimer des nœuds via l’API. JavaFX 2.2 a rajouté l’API snapshot qui permet de réaliser des captures bitmap des nœuds, ce qui rendait alors possible de sauvegarder des images ou encore des PDF. Par contre, il n’y avait pas du tout de support de l’impression. Il était cependant possible d’en bidouillant un, via le support d’impression de AWT/Swing ou via le Print Services (package javax.print). Manque de bol, ça fonctionnait très bien sous Linux et Windows mais pas du tout sur MacOS car sur cette plateforme, JavaFX tourne en mode headless, sans AWT et Swing. Pareil sur ARM (Raspberry Pi et autres) j’imagine.
JavaFX 8 introduit donc un support de l’impression qui semble être un mélange des API AWT/Swing et Print Services, c’est a dire qu’on va retrouver grosso-modo les mêmes classes permettant de définir les imprimantes ou les feuilles (Printer, Paper, etc.) ou la tache d’impression en elle-même (PrinterJob). La seul vraie différence, pour ce que j’en ai vu, c’est qu’on passe d’une mise en page passive, via l’interface Printable qui est appelée lorsque la page est envoyée à l’imprimante dans AWT/Swing, à une mise en page active avant l’impression.
[...]
final Button printTestButton = new Button("Print test");
printTestButton.setOnAction(new EventHandler() {
@Override
public void handle(ActionEvent actionEvent) {
// Création du job d'impression.
final PrinterJob printerJob = PrinterJob.createPrinterJob();
// Affichage de la boite de dialog de configation de l'impression.
if (printerJob.showPrintDialog(printTestButton.getScene().getWindow())) {
// Mise en page, si nécessaire.
// Lancement de l'impression.
if (printerJob.printPage(printTestButton)) {
// Fin de l'impression.
printerJob.endJob();
}
}
}
});
En l’état actuel des choses, sous Windows (pas encore testé sous Linux et MacOS), l’appel à printerJob.showPrintDialog() fait apparaitre la même boite de dialogue que celle des Print Services. L’appel à printPage() rajoute une page dans la tache d’impression, et l’appel à endJob() indique qu’il n’y a plus de nouvelles pages à attendre.
La doc nous informe que l’impression peut être lancée sur le JavaFX Application Thread ou pas, que le nœud peut être attaché à la scène ou pas. Il faudra prendre exactement les mêmes précautions que pour un snapshot, à savoir que, si le nœud est dans la scène, il ne faudra surtout pas faire des manipulations depuis des threads tiers sous peine d’exception. De plus, tout déplacement ou changement dans le layout ou l’apparence du noeud sera répercuté dans la scène après l’impression si on ne pense pas à les annuler. Également, si le nœud est animé, l’impression peut, sans le faire exprès, capturer des états intermédiaires entre deux animations ce qui peut donner des résultats pas géniaux.
On aura donc plutôt tendance à copier le contenu de la scène en créant / clonant les nœuds existants / rechargeant une seconde fois les FXML, ou en créant une nouvelle arborescence de nœuds hors-écran (quand on veut créer des rapports, etc.) et à faire la mise en page avant d’envoyer le nœud racine à l’impression. Il faudra penser également à redimensionner le nouveau contenu à la taille de la zone imprimable qu’on peut récupérer via les options de la tache d’impression et à calculer le nombre de pages à imprimer (quand quelque chose s’étale sur plusieurs pages) et entre chaque appel à printPage(), soit faire des translations de layoutY (si on imprime un nœud unique), soit construire l’arborescence de la page suivante.
final JobSettings settings = printerJob.getJobSettings();
final PageLayout pageLayout = settings.getPageLayout();
final double pageWidth = pageLayout.getPrintableWidth();
final double pageHeight = pageLayout.getPrintableHeight();
// Effectuer la mise en page qui s'impose...
[...]
Note : actuellement, tout comme avec snapshot, si on imprime des graphes (LineChart, etc.) qui sont construits hors-écran, la légende et les axes (labels, nom de l’axe, tick) ne s’affichent pas et ce même si on a mis la propriété animated du graphe et de ses axes à la valeur false. C’est un problème connu pour lequel il existe déjà plusieurs requêtes sur le JIRA de JavaFX.
Commentaires récents
- Back from the future… dans
- Back from the future… dans
- Static linking = does not Compute dans
- Paquetage x 2 dans
- Why you little… dans