
Il faut dire que le COVID, plusieurs confinements, et des changements de r�gles cot� boulot ont fait que poster sur un blog �tait devenu peu pratique. De plus, ces derni�res ann�es, mon r�le se limite plut�t � faire de l�administration syst�me que du d�veloppement.
Il n'aura �chapp� � personne que, ces derniers temps, Java semble �tre, euh, au creux de la vague... et ce pour diverses raisons sur lesquelles nous ne nous �tendrons pas. Bien que Kotlin de JetBrains existe depuis 2011, ce n'est que depuis 2019 qu'il a pris son essor quand Google a d�cid� d'en faire le langage de d�veloppement pr�f�r� pour Android. Outre le fait que AndroidStudio soit bas� sur IntelliJ IDEA de JetBrains, sans doute auront-ils jug� le langage assez mature et suffisamment compatible avec la JVM au c�ur de leur OS mobile. Bien que j'utilise IDEA depuis un peu plus de 10 ans d�j�, je ne m��tais encore jamais pench� jusqu'� pr�sent sur Kotlin. J'ai vu qu'il existe un framework JavaFX pour Kotlin nomm� TornadoFX mais il ne semble plus �tre maintenu et je ne suis pas totalement s�r de l�int�r�t de l'utiliser �tant donn� que, en th�orie, on devrait pouvoir directement �crire une app JavaFX en Kotlin sans trop de difficult�.
Pr�requis
Vous avez besoin de :
- La derni�re version de IntelliJ IDEA Community avec le support de Java et Kotlin ;
- Une version r�cente de l'OpenJDK (20 ou 21 feront l'affaire) ;
- Une version r�cente du SDK JavaFX (20 ou 21 feront l'affaire) pour votre OS � t�l�charger chez Gluon (ou un autre fournisseur) ;
- Une version r�cente des fichiers JMOD de JavaFX (20 ou 21 feront l'affaire) pour votre OS � t�l�charger chez Gluon (ou un autre fournisseur) - cela sera utile pour la cr�ation d'une application native.
Optionnel et non couvert par ce blog:
- De quoi signer num�riquement votre JAR ;
- De quoi signer num�riquement votre ex�cutable Windows ou macOS ;
- Un cr�ateur d'installeur pour Windows (cependant jpackage peut directement cr�er des paquets RPM ou DEB pour Linux ou des images DMG pour macOS ainsi que des installeurs MSI pour Windows)
- De quoi signer num�riquement votre installeur Windows ou votre image macOS.
D�sarchivez votre JDK et votre SDK JavaFX dans des emplacements vides. Personnellement, je place en g�n�ral les fichiers JMOD de JavaFX dans un r�pertoire jmods dans la racine du SDK JavaFX mais vous pouvez les mettre o� bon vous semble.
Installez ensuite IntelliJ IDEA, puis lancez l'IDE.
Cr�ation du projet
Sur l��cran d�accueil, optez pour la cr�ation d'un nouveau projet vide en faisant New Project mais ne choissisez pas un g�n�rateur pr�d�fini. Dans la configuration de ce projet vide, donnez-lui un nom, puis choisissez Kotlin au lieu de Java en tant que Langage. Si le JDK qui vous int�resse n'est pas disponible, allez dans le menu d�roulant JDK et faites Add SDK puis naviguez vers la racine de votre copie du JDK avant de valider votre choix. S�lectionnez ce JDK � votre retour dans la configuration du projet. V�rifiez que tous vos r�glages sont corrects et appuyez sur Create.
Une fois, le projet g�n�r�, vous pouvez aller dans File -> Project Structure... ou cliquez avec le bouton de droite sur le n�ud racine du projet et choisissez Open Module Settings. Allez dans Libraries, et appuyez sur le bouton + en haut de la colonne listant les biblioth�ques (ne pas appuyer sur le bouton + dans l��cran d�taillant le contenu du runtime Kotlin pour Java, cela a pour effet d'ajouter des fichiers a la biblioth�que s�lectionn�e). Dans Project Library, choisissez Java et naviguez jusqu'au r�pertoire lib contenu dans votre SDK JavaFX, puis s�lectionnez tous les fichiers JAR avant d'appuyer sur OK. Lorsque Intellj IDEA vous demande d'ajouter la biblioth�que � votre projet, faite Cancel. Dans la colonne listant les biblioth�ques, vous pouvez sans doute voir que IDEA vous a rajout� une biblioth�que nomm�e javafx-swt ou quelque chose de similaire. Donnez-lui un nom correct, genre javafx-21, en �ditant le champ Name sur l��cran d�taillant le contenu de cette biblioth�que. Pensez � appuyer sur Apply en bas de boite de dialogue pour valider ce changement de nom.
Au niveau du projet, basculez d�sormais sur les r�glages Modules, puis dans l'onglet Dependancies. Appuyez sur le bouton + situes sous l�entr�e Module SDK. Choisissez Library... et s�lectionnez votre nouvelle biblioth�que JavaFX javafx-21 avant de faire Add Selected. Vous pouvez maintenant fermer les r�glages du projet en appuyant sur le bouton OK en bas de la boite de dialogue.

Une fois de retour dans la vue principale du projet, d�pliez l'arborescence src -> main -> kotlin et cliquez avec le bouton de droite sur le n�ud kotlin et faites New -> Package. Donnez le nom test � ce package. Puis, cliquez une fois de plus avec le bouton de droite sur le n�ud kotlin et faites New -> module-info.java. Cela cr�era un nouveau fichier module-info.java sous le n�ud kotlin dans lequel vous pouvez mettre l��bauche de module suivante :
Code Java : | S�lectionner tout |
1 2 3 | module test { exports test; } |
Application basique
Nous allons commencer par une application JavaFX tr�s simple : afficher une fen�tre vide. Cliquez avec le bouton de droite sur le n�ud test (celui qui correspond au package) et faites New -> Java Class. Appelez cette nouvelle classe MainFX et validez. Vous pouvez saisir le code suivant dans votre classe :
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package test; import javafx.application.Application; import javafx.stage.Stage; public final class MainFX extends Application { public static void main(final String... args) { Application.launch(args); } @Override public void start(final Stage stage) throws Exception { stage.setTitle("Test FX"); stage.setWidth(800); stage.setHeight(600); stage.show() } } |
Tout ce que fait ce code est d'initialiser une application, de configurer sa fen�tre en lui donnant un titre et des dimensions, puis de l'afficher.
Si le SDK JavaFX est correctement install� et d�tect� par IntelliJ (voir plus haut), l'IDE vous indiquera des erreurs dans le code, et surtout soulignera une partie des lignes d'importation de classe en rouge. En passant votre curseur dessus, une infobulle vous indiquera que vous avez besoin de rajouter des modules manquants � l'appel. Cliquez sur une des lignes fautives et faites ALT+ENTR�E au clavier, puis choisissez Add required 'javafx.graphics' directive to module-info.java.... Cela ajoutera la ligne requires javafx.graphics; dans votre fichier module-info.java et devrait enlever toutes les erreurs pr�sentes dans votre classe.
Dans l'arborescence du projet, cliquez avec le bouton de droite sur le n�ud MainFX et choisissez Run 'MainFX.main()'. Une fois votre code compil�, la fen�tre vide de notre application de test de devrait appara�tre sur l��cran. C'est bien, mais on veut faire la m�me chose en Kotlin, non ? Fermez votre fen�tre et cliquez avec le bouton de droite sur le n�ud du package test, puis choisissez New -> Kotlin Class/File, et donnez le nom MainKt � cette nouvelle classe. Vous pouvez mettre le contenu suivant dans cette classe :
Code Kotlin : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | package test import javafx.application.Application import javafx.stage.Stage class MainKt : Application() { override fun start(stage: Stage) { stage.title = "Test Kt" stage.width = 800.0 stage.height = 600.0 stage.show() } } |
On peut voir que, bien que similaire, le code Kotlin est un peu moins verbeux que le code Java. La d�claration d�h�ritage permet directement l'invocation d'un constructeur de la classe parente pouvant prendre des param�tres. Outre l'absence de ; en fin de ligne (ils sont optionnels), je n'ai pas eut besoin d�invoquer un setter pour changer le titre de la fen�tre ou encore ses dimensions. Par contre j'ai du changer mes valeurs num�riques enti�res en nombres flottants car Kotlin utilise un typage plus fort que Java. �galement, dans la d�claration des param�tres de ma m�thode (d�sormais une fonction), le nom de la variable vient avant son type. Reste un soucis, comment lancer cette application ? Contrairement � Java, Kotlin n'a pas le concept de membre ou de m�thode statiques dans les classes. Or nous en utilisions 2 pr�c�demment : main() qui est le point de lancement habituel des programmes Java et Application.launch() qui permet d'initialiser une app JavaFX (en initialisant les runtimes au passage, en cr�ant une instance de notre classe et en g�rant automatiquement tout ce qui est cr�ation de la fen�tre native, avant d'invoquer la methode start() de notre classe avec la fen�tre en param�tre).
Le premier soucis est assez simple � g�rer : il suffit de d�clarer une fonction main() globale qui servira � faire la m�me chose. Il vous suffit donc de placer la fonction suivante en dehors du corps de la classe :
Code Kotlin : | S�lectionner tout |
1 2 3 | fun main() { println("Hello World!") } |
IDEA soulignement imm�diatement println() en rouge en indiquant dans une infobulle que la fonction println() est d�finie dans le module kotlin.stdlib et que ce dernier est absent de notre projet. Vous pouvez corriger ce soucis en choisissant Add required 'kotlin.stdlib' directive to module-info.java... directement dans l'infobulle ou en faisant ALT+ENTR�E sur la ligne incrimin�e. Cela rajoutera la ligne requires kotlin.stdlib; dans votre fichier module-info.java et devrait enlever toutes les erreurs pr�sentes dans votre classe. D�sormais, notre fichier module-info.java ressemble � cela :
Code Java : | S�lectionner tout |
1 2 3 4 5 | module test { requires javafx.graphics; requires kotlin.stdlib; exports test; } |
Dans l'arborescence du projet, cliquez avec le bouton de droite sur le n�ud MainKt.kt et choisissez Run 'MainKt' pour voir s'afficher "Hello World!" sur votre sortie.
� noter que les variantes suivantes sont �galement valides pour d�crire un point de lancement Kotlin :
- fun main(args: Array<String>) - cette fonction accepte un tableau de cha�nes de caract�res qui sont les param�tres pass�s sur la ligne de commande.
- fun main(vararg args: String) - cette fonction accepte un nombre variable de cha�nes de caract�res qui sont les param�tres pass�s sur la ligne de commande.
Le second soucis est un poil plus emb�tant : il nous faut arriver � invoquer Application.launch(). Kotlin nous permet de simuler des m�thodes statiques en ajoutant un membre compagnon dans une classe. Par exemple en faisant :
Code Kotlin : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package test import javafx.application.Application import javafx.stage.Stage class MainKt : Application() { companion object { fun launch(args: Array<String>) { Application.launch(args) } } override fun start(stage: Stage) { stage.title = "Test Kt" stage.width = 800.0 stage.height = 600.0 stage.show() } } fun main(args: Array<String>) { MainKt.launch(args) } |
Mais l'IDE va imm�diatement souligner la ligne Application.launch(args) en rouge en nous indiquant qu'elle ne peut pas trouver de surcharge de la m�thode qui fonctionne avec les types des arguments que nous utilisons. Cela vient du fait que les varargs et tableaux en Kotlin ne sont pas tout � fait g�r�s de la m�me mani�re que leurs �quivalents Java. On peut r�gler ce probl�me en utilisant le spread operator de Kotlin pour permettre de passer les �l�ments contenus dans la variable individuellement. Cet op�rateur s��crit sous la forme d'une * plac�e devant la variable. La ligne devient donc :
Code Kotlin : | S�lectionner tout |
1 2 3 | fun launch(args: Array<String>) { Application.launch(*args) } |
Cependant, notre solution ne fonctionne toujours pas car l�ex�cution le programme va �chouer avec l'erreur suivante :
Code console : | S�lectionner tout |
1 2 3 4 5 | Exception in thread "main" java.lang.RuntimeException: Error: class test.MainKt$Companion is not a subclass of javafx.application.Application at javafx.graphics@21.0.1/javafx.application.Application.launch(Application.java:305) at test/test.MainKt$Companion.launch(MainKt.kt:9) at test/test.MainKtKt.main(MainKt.kt:20) at test/test.MainKtKt.main(MainKt.kt) |
En effet, la m�thode statique Application.lauch() qui permet de d�marrer une application JavaFX s'attend � ce que la classe dans laquelle elle est invoqu�e h�rite de Application Or, l'objet compagnon est compil� dans une classe interne (la trace mentionne MainKt$Companion) qui n�h�rite pas de Application. Heureusement, il existe une variante de Application.lauch() qui permet de sp�cifier quelle classe doit �tre utilis�e pour initialiser l'app. On peut donc transformer le code en Application.launch(MainKt::class.java, *args) en utilisant la syntaxe MainKt::class.java qui permet de r�cup�rer la r�f�rence sur la classe Java. Ce qui nous donne :
Code Kotlin : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package test import javafx.application.Application import javafx.stage.Stage class MainKt : Application() { companion object { fun launch(vararg args: String) { Application.launch(MainKt::class.java, *args) } } override fun start(stage: Stage) { stage.title = "Test Kt" stage.width = 800.0 stage.height = 600.0 stage.show() } } fun main(vararg args: String) { MainKt.launch(*args) } |
En observant ce code, on se rend compte que notre appel est finalement totalement d�tach� de la classe MainKt (plus rien de nous oblige � initialiser le toolkit depuis l�int�rieur de la classe) , ce qui nous permet de nous affranchir de la classe compagnon et de simplifier le code en :
Code Kotlin : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package test import javafx.application.Application import javafx.stage.Stage class MainKt : Application() { override fun start(stage: Stage) { stage.title = "Test Kt" stage.width = 800.0 stage.height = 600.0 stage.show() } } fun main(vararg args: String) { Application.launch(MainKt::class.java, *args) } |
Vous pouvez � nouveau ex�cuter votre code Kotlin pour voir appara�tre une fen�tre identique � celle produite par le code Java � l'exception du titre de la fen�tre. F�licitations !
Application avanc�e
C'est sympa mais on a juste une fen�tre vide � l'ecran. Nous allons maintenant modifier notre app pour afficher des contr�les et la rendre plus int�ressante avec avec un graphique en ligne. Une fois de plus je vais commencer par modifier l'application Java pour donner une r�f�rence de ce que doit �tre l'application finale avant de passer sur la version Kotlin.
Dans l�arborescence de votre projet, cliquez avec le bouton de droite sur le n�ud src -> resources puis choisissez New -> Directory et donnez � ce nouveau r�pertoire le m�me nom que notre package (ici test). Faites un clic droit sur ce nouveau r�pertoire et choisissez New -> File, puis nommez ce fichier strings.properties. �ditez ce fichier et collez ce contenu dedans :
Code Properties : | S�lectionner tout |
1 2 3 4 5 | app.title.fx = Test FX app.title.kt = Test Kt xaxis.label = abscisses yaxis.label = ordonn�es series.label = y = x� |
Faites une seconde fois un clic droit sur ce nouveau r�pertoire et choisissez New -> File et nommez ce fichier app.css. �ditez ce fichier et collez ce contenu dedans :
Code CSS : | S�lectionner tout |
1 2 3 | .root { -fx-background-color: white; } |
Vous allez maintenant modifier le contenu de la m�thode start() classe Java MainFX comme suit :
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | final var bundle = ResourceBundle.getBundle("test/strings"); // Création du graphique. final var series = new LineChart.Series<Number, Number>(); series.setName(bundle.getString("series.label")); IntStream.rangeClosed(0, 10) .forEach(x -> { final double y = Math.pow(x, 2); final var data = new XYChart.Data<Number, Number>(x, y); series.getData().add(data); }); final var xAxis = new NumberAxis(0, 10, 5); xAxis.setLabel(bundle.getString("xaxis.label")); final var yAxis = new NumberAxis(0, 100, 10); yAxis.setLabel(bundle.getString("yaxis.label")); final var chart = new LineChart<>(xAxis, yAxis); chart.getData().add(series); // Mise en place de la scène. final var root = new StackPane(); root.getChildren().setAll(chart); var scene = new Scene(root); // Gestion des CSS. Optional.ofNullable(getClass().getResource("app.css")) .map(URL::toExternalForm) .ifPresent(scene.getStylesheets()::add); // Gestion de la fenêtre. stage.setTitle(bundle.getString("app.title.fx")); stage.setWidth(800); stage.setHeight(600); stage.setScene(scene); stage.show(); |
IntelliJ va sans doute se plaindre que le module javafx.controls est absent. Placez votre curseur sur une des lignes d'importation incrimin�es et faites ALT+ENTR�E au clavier pour proc�der � cette correction. D�sormais, notre fichier module-info.java ressemble � cela :
Code : | S�lectionner tout |
1 2 3 4 5 6 | module test { requires javafx.graphics; requires javafx.controls; requires kotlin.stdlib; exports test; } |
Parmi les choses qui sont faites par ce code :
- On initialise un gestionnaire de ressources localis�es qui va permettre d'extraire les cha�nes de texte depuis le fichier strings.properties ;
- On cr�e un graphique en ligne qui permet d'afficher les valeurs du carr� des nombres entiers entre 0 et 10 (inclus) ;
- On cr�e tous les composants et la sc�ne n�cessaire pour afficher ce graphique ;
- On charge le fichier CSS app.css et on l'applique sur la sc�ne ;
- On place la sc�ne dans notre fen�tre.
Le code bien que verbeux n'est pas tr�s compliqu�.
Maintenant, vous allez copier ce code Java et... le coller dans le code de la fonction start() dans la classe Kotlin MainKt ! En effet, IntelliJ va d�tecter que ce code est en Java et va vous proposer de traduire automatiquement ce code Java en code Kotlin ce qui prend juste quelques secondes. Et il est plut�t efficace � cette tache :
Code Kotlin : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | val bundle = ResourceBundle.getBundle("test/strings") // Création du graphique. // Création du graphique. val series = Series<Number, Number>() series.name = bundle.getString("series.label") IntStream.rangeClosed(0, 10) .forEach { x: Int -> val y: Double = x.pow(2.0) val data = XYChart.Data<Number, Number>(x, y) series.data.add(data) } val xAxis = NumberAxis(0.0, 10.0, 5.0) xAxis.label = bundle.getString("xaxis.label") val yAxis = NumberAxis(0.0, 100.0, 10.0) yAxis.label = bundle.getString("yaxis.label") val chart = LineChart(xAxis, yAxis) chart.data.add(series) // Mise en place de la scène. // Mise en place de la scène. val root = StackPane() root.children.setAll(chart) val scene = Scene(root) // Gestion des CSS. // Gestion des CSS. Optional.ofNullable(javaClass.getResource("app.css")) .map { obj: URL -> obj.toExternalForm() } .ifPresent { e: String? -> scene.stylesheets.add(e) } // Gestion de la fenêtre. // Gestion de la fenêtre. stage.title = bundle.getString("app.title.fx") stage.width = 800.0 stage.height = 600.0 stage.scene = scene stage.show() |
Quelques soucis mineurs au final : tous mes commentaires ont �t� doubl�s et la fonction pow() semble �tre manquante. Pour les commentaires, c'est facilement corrigeable. Pour la fonction cela est du au fait que la fonction pow() est uniquement d�finie pour les nombres flottants et pas pour les nombres entiers. Il est possible de corriger le soucis en faisant : val y: Double = x.toDouble().pow(2.0). IntelliJ soulignera la ligne en rouge une derni�re fois, il suffit de faire ALT+ENTR�E au clavier sur cette ligne pour rajouter l'import manquant import kotlin.math.pow en d�but de fichier. Profitez-en pour changer la cl� de ressource du titre de la fen�tre de stage.title = bundle.getString("app.title.fx") en stage.title = bundle.getString("app.title.kt"). Ce qui nous donne apr�s un tr�s court nettoyage du code :
Code Kotlin : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | package test import javafx.application.Application import javafx.scene.Scene import javafx.scene.chart.LineChart import javafx.scene.chart.NumberAxis import javafx.scene.chart.XYChart import javafx.scene.chart.XYChart.Series import javafx.scene.layout.StackPane import javafx.stage.Stage import java.net.URL import java.util.* import java.util.stream.IntStream import kotlin.math.pow class MainKt : Application() { override fun start(stage: Stage) { val bundle = ResourceBundle.getBundle("test/strings") // Création du graphique. val series = Series<Number, Number>() series.name = bundle.getString("series.label") IntStream.rangeClosed(0, 10) .forEach { x: Int -> val y: Double = x.toDouble().pow(2.0) val data = XYChart.Data<Number, Number>(x, y) series.data.add(data) } val xAxis = NumberAxis(0.0, 10.0, 5.0) xAxis.label = bundle.getString("xaxis.label") val yAxis = NumberAxis(0.0, 100.0, 10.0) yAxis.label = bundle.getString("yaxis.label") val chart = LineChart(xAxis, yAxis) chart.data.add(series) // Mise en place de la scène. val root = StackPane() root.children.setAll(chart) val scene = Scene(root) // Gestion des CSS. Optional.ofNullable(javaClass.getResource("app.css")) .map { obj: URL -> obj.toExternalForm() } .ifPresent { e: String? -> scene.stylesheets.add(e) } // Gestion de la fenêtre. stage.title = bundle.getString("app.title.kt") stage.width = 800.0 stage.height = 600.0 stage.scene = scene stage.show() } } fun main(vararg args: String) { Application.launch(MainKt::class.java, *args) } |
Parmi les choses qu'on peut remarquer : Kotlin utilise le mot-cl� val qui est similaire � la combinaison final var en Java. Ces variables ne sont donc pas mutables apr�s leur d�claration. Pour d�clarer des variables mutables, il faut utiliser � la place le mot-cl� var. D'ailleurs les param�tres des functions sont aussi non-mutables tant qu'on y est. De plus, Kotlin n'utilise pas le mot-cl� new quand il faut cr�er de nouvelles instances. Le bloc lambda Kotlin ressemble � son anc�tre Java. Pour le reste, au niveau de la r�solution des resources sur le CLASSPATH, et bien cela fonctionne exactement comme en Java basique et this.getClass() est devenu javaClass.
Au lancement, notre application Kotlin + JavaFX se pr�sente et se comporte exactement comme son �quivalent 100% Java. Il y a probablement des choses qui pourraient �tre simplifi�es en utilisant plus de fonctions ou d'idiomes de Kotlin (pour, entre autres, la gestion des valeurs potentiellement null) mais c'est d�j� un bon d�part.
Fichier JAR
Nous allons maintenant cr�er un JAR pour permettre de distribuer plus facilement notre application. Allez dans le menu File -> Project Structure... ou cliquez avec le bouton de droite sur le n�ud racine de votre projet et choisissez Open Module Settings. D�placez-vous dans l'onglet Artifact et cliquez sur le bouton + et choisissez JAR -> From module with dependencies.... Dans Main Class, vous allez sp�cifier la classe qui sert � lancer le programme, celle qui contient la fonction main(). Or, souvenez-vous que cette fonction est globale et ne fait pas partie de la classe test.MainKt. Si vous d�pliez la boite d�roulante, vous verrez qu'il existe dans votre projet une 3e classe nomm�e test.MainKtKt (un second "Kt" a �t� ajout� � son nom) qui a �t� g�n�r�e � la compilation. C'est cette classe qui contient la fonction main(). S�lectionnez-la et validez, puis cr�ez votre art�fact sans changer d'autres options.
L'onglet Artifact d�taillle d�sormais le contenu de votre nouvel art�fact. Commencez par changer son nom en MainKt. Puis s�lectionnez le n�ud racine qui correspond au fichier JAR et cliquez avec le bouton de droite puis choissiez l'action Rename et renommez-le en MainKt.jar et appuyez sur ENTR�E pour valider. Dans la liste des JAR qui seront recopi�s dans votre archive, suprimez tous les JAR de JavaFX (et uniquement ceux-ci). Conservez les autres JAR tierces comme les biblioth�ques de Kotlin ou encore la biblioth�que des annotation Java. Validez en cliquant sur OK. En revenant vers votre projet, vous pouvez voir que l'IDE a ajout� un fichier manifeste dans vos ressources.
Vous pouvez maintenant compiler votre fichier JAR en allant dans le menu Build -> Build Artifacts... puis en choisissant MainKT -> Build. Au bout de quelques secondes, la nouvelle archive cr��e devrait se trouver dans le r�pertoire out/artifacts/MainKt de votre projet.
Une fois votre JAR obtenu, c'est le bon moment pour le signer avec un certificat num�rique avant de proc�der � sa distribution.
Lanceur natif
Il est temps maintenant de cr�er un lanceur natif pour votre programme. Cela permet d'�viter de devoir fournir des scripts de lancemnent a vos utilisateurs et ainsi eviter la presence parfois insolites de fenetres d'intepreteur de commande sur leur �cran. Pour cela, nous allons utiliser l'outils jpackage qui est fourni dans le JDK.
Utilisez votre explorateur de fichier ou votre interpr�teur de commandes favori suivant votre plateforme et d�placez-vous dans le r�pertoire racine de votre projet. Cr�ez un sous-r�pertoire package et placez-y le contenu suivant. Vous pouvez utiliser des services en lignes pour convertir une images PNG en icones Windows ICO ou macOS ICNS :
Code : | S�lectionner tout |
1 2 3 4 5 6 7 | package ├── linux │ └── MainKt.png ├── macos │ └── MainKt.icns └── windows └── MainKt.ico |
Code : | S�lectionner tout |
1 2 3 4 | bin ├── package.bat ├── package_linux.sh └── package_macos.sh |
Code CMD : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | @echo off set JAVA_HOME="C:\Program Files\java\jdk-21.0.1\" set PATH=%JAVA_HOME%\bin;%PATH% java -version set APP_NAME=MainKt set APP_TYPE=app-image set APP_ICON=./package/windows/%APP_NAME%.ico set MAIN_JAR=%APP_NAME%.jar set MODULES=javafx.graphics,javafx.controls set INPUT_DIR=out\artifacts\%APP_NAME% set OUTPUT_DIR=redist set FX_HOME=E:\fabriceb\Devel\Java\lib\JavaFX\javafx-sdk-21.0.1 set FX_LIBS=%FX_HOME%\lib set FX_JMODS=%FX_HOME%\jmods if exist %OUTPUT_DIR%\%APP_NAME% rmdir /s /q %OUTPUT_DIR%\%APP_NAME% if not exist %OUTPUT_DIR% mkdir %OUTPUT_DIR% REM Test the app works. REM java --module-path $FX_LIBS --add-modules $MODULES -jar $INPUT_DIR/$MAIN_JAR REM Create native launcher. jpackage --type %APP_TYPE% --input %INPUT_DIR% --name %APP_NAME% --main-jar %MAIN_JAR% --module-path %FX_JMODS% --add-modules %MODULES% --dest %OUTPUT_DIR% --icon %APP_ICON% |
La version Windows g�n�re directement un lanceur natif ex�cutable. Il est possible de g�n�rer un installeur MSI, consultez la documentation de jpackage.
Pour Linux : package_linux.sh
Code bash : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #!/bin/sh JAVA_HOME=/usr/local/java/jdk-21.0.1 PATH=$JAVA_HOME/bin:$PATH java -version APP_NAME=TestKt APP_TYPE=app-image APP_ICON= MAIN_JAR=$APP_NAME.jar MODULES=javafx.graphics,javafx.controls INPUT_DIR=./out/artifacts/$APP_NAME OUTPUT_DIR=redist FX_HOME=/home/fabriceb/devel/java/lib/javafx/javafx-sdk-21.0.1 FX_LIBS=$FX_HOME/lib FX_JMODS=$FX_HOME/jmods if [[ -d $OUTPUT_DIR/$APP_NAME ]]; then rm -rf $OUTPUT_DIR/$APP_NAME fi mkdir -p $OUTPUT_DIR # Test the app works. #java --module-path $FX_LIBS --add-modules $MODULES -jar $INPUT_DIR/$MAIN_JAR # Create native launcher. jpackage --type $APP_TYPE --input $INPUT_DIR --name $APP_NAME --main-jar $MAIN_JAR --module-path $FX_JMODS --add-modules $MODULES --dest $OUTPUT_DIR |
La version Linux g�n�re directement un lanceur natif ex�cutable ; cet ex�cutable ne prend pas d'icone mais il reste possible de fournir une image PNG pour personaliser un raccourci servant � lancer l'application dans votre interface graphique. Il est possible de g�n�rer des paquets RPM ou DEB pour votre distribution, consultez la documentation de jpackage.
Pour macOS : package_macos.sh
Code bash : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #!/bin/sh JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-21.0.1.jdk/Contents/Home/ PATH=$PATH:$JAVA_HOME/bin APP_NAME=MFCL-Viewer APP_TYPE=app-image APP_ICON=./package/macosx/$APP_NAME.icns MAIN_JAR=mfcl.viewer.jar MODULES=javafx.graphics,javafx.controls INPUT_DIR=./out/artifacts/mfcl_viewer_jar OUTPUT_DIR=redist FX_HOME=/Users/fabriceb/devel/lib/javafx/javafx-sdk-21.0.1 FX_LIBS=$FX_HOME/lib FX_JMODS=$FX_HOME/jmods if [[ -d $OUTPUT_DIR/$APP_NAME ]]; then rm -rf $OUTPUT_DIR/$APP_NAME fi mkdir -p $OUTPUT_DIR # Test the app works. #java --module-path $FX_LIBS --add-modules $MODULES -jar $INPUT_DIR/$MAIN_JAR # Create native launcher. jpackage --type $APP_TYPE --input $INPUT_DIR --name $APP_NAME --main-jar $MAIN_JAR --module-path $FX_JMODS --add-modules $MODULES --dest $OUTPUT_DIR --icon $APP_ICON |
La version macOS g�n�re directement un r�pertoire d'application. Il est possible de g�n�rer un paquet PKG ou une image DMG si besoin, consultez la documentation de jpackage.
Nous utilisons l'outil jpackage du JDK pour cr�er un lanceur natif pour votre applicaiton sur votre systeme d'exploitation. Si vous souhaitez porter votre app vers un syst�me d'exploitation diff�rent, vous n'avez pas besoin de recompiler specialement votre projet Kotlin pour ce nouvel OS. Tout ce que vous avez besoin de faire est d'installer un JDK sur le nouvel OS ainsi que de r�cup�rer les fichiers JMODS de JavaFX pour cet OS. Vous pouvez ensuite copier le fichier JAR, les scripts de packaging et les icones d'applications existants aux endroits appropri�s, puis de modificer, si n�cessaire, les chemins d'acc�s dans le script correspondant � cet OS, avant d'executer ce script.
La suite ?
Si vous �tes sous Windows, par exemple, c'est le bon moment de signer votre lanceur natif avec un certificat Microsoft Authenticode. Vous pouvez ensuite empaqueter tous les fichiers g�n�r�s par jpackage avec un cr�ateur d'installeur (InnoSetup, etc.).
De m�me, si vous �tes sur macOS, c'est �galement une bonne �tape pour signer votre application ou votre image avec un certificat de d�veloppeur Apple.
Conclusion
Voila, vous avez cr�� une application JavaFX en Kotlin et vous pouvez d�sormais la distribuer � vos utilisateurs. M�me si le code Kotlin prend moins de place et est un peu plus facile � lire que son equivalent Java, on peut se rendre compte qu'il ne sont pas si eloign�s l'un de l'autre tant qu'on continue � utiliser des bliblioth�ques Java. Grace � la grande efficacit� de la traduction automatique du code offerte par IntelliJ IDEA nous n'avons pas perdu �norm�ment de temps en portant du code existant Java en code Kotlin. Le challenge serait maintenant de cr�er une application JavaFX dont le c�ur de metier serait �crit en Kotlin pur. Cependant, concevoir et cr�er une nouvelle application JavaFX directement en Kotlin ne semble pas non-plus etre une tache totalement insurmontable une fois qu'on a appr�hend� les bases du language et de son API.
Vous avez lu gratuitement 0 articles depuis plus d'un an.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer � vous proposer des publications.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer � vous proposer des publications.