IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaFX Discussion :

[JavaFX - Gradle] chargement d'une resource FXML dans un autre controller FXML


Sujet :

JavaFX

  1. #1
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2015
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2015
    Messages : 76
    Points : 58
    Points
    58
    Par défaut [JavaFX - Gradle] chargement d'une resource FXML dans un autre controller FXML
    Salut à tous,

    J'essaie de mettre en place un projet JavaFX qui est buildé par l'intermédiaire de Gradle.
    j'essaie d'implémenter le principe d'un controller FXML dédié à ma menuBar qui se chargera LUI de changer le contenu de ma scene ou autres.
    J'ai donc pour cela besoin qu'un controller FXML puisse en charger un autre afin d'obtenir le root Node et l'inseré ou je le souhaite.

    J'arrive à builder et runner l'application sans problème.
    Mais lorsque j'essaie de charger un FXML dans un autre controller FXML c'est toujours une problématique d'url ou de path.

    J'essaie à travers ce controller :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    54
     
    package compty.controller;
     
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.layout.BorderPane;
    import java.io.IOException;
     
    public class MainScreenController
    {
        @FXML
        private BorderPane borderPane;
     
        @FXML
        private void handleMenuSimulationAchat(ActionEvent event) throws IOException
        {
            System.out.println("je suis ici 1");
     
            this.displaySimulationAchatScreen();
        }
     
        public void displaySimulationAchatScreen() throws IOException
        {
            FXMLLoader loader = new FXMLLoader();
     
            loader.setLocation(getClass().getClassLoader().getResource("/compty/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getClassLoader().getResource("compty/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getClassLoader().getResource("/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getClassLoader().getResource("/resources/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getClassLoader().getResource("resources/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getClassLoader().getResource("compty/resources/views/simulationAchat.fxml"));
     
            loader.setLocation(getClass().getResource("/resources/main/compty/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("/resources/compty/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("/resources/simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("/resources/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("resources/main/compty/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("resources/compty/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("resources/simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("resources/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("/compty/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("/main/compty/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("/main/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("/views/simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("views/simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("simulationAchat.fxml"));
            loader.setLocation(getClass().getResource("/simulationAchat.fxml"));
     
            Parent root = loader.load();
     
            this.borderPane.setCenter(root);
        }
    de charger le fichier FXML suivant simulationAchat.fxml. J'ai laissé l'ensemble de mes tests visible afin de vous monter toutes mes tentatives infructueuses.
    Je sais que l'url est chargé à l'éxecution et donc à partir de la structure du Jar et non de mon code source.

    Je vous mets l'architecture de mon code source ainsi que de mon Jar compilé.

    Nom : Capture d’écran 2020-09-28 à 16.06.05.png
Affichages : 776
Taille : 126,1 Ko
    Nom : Capture d’écran 2020-09-29 à 13.46.30.png
Affichages : 763
Taille : 119,5 Ko

    Néanmoins malgré le fait d'essayer des tas de combinaisons d'URL différentes je n'arrive jamais à charger mon fichier FXML.

    D'après la structure de mon code présenté, quel serait d'après vous le bon Path à fournir à la methode getResource() afin d'obtenir ce fameux fichier FXML à travers le FXMLLoader ?

    Voici également mon fichier build.gradle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    plugins {
        id 'application'
        id 'org.openjfx.javafxplugin' version '0.0.9'
    }
     
    java {
        modularity.inferModulePath = true
    }
     
    javafx {
        version = "14"
        modules = [
            'javafx.base',
            'javafx.controls',
            'javafx.fxml'
        ]
    }
     
    sourceSets {
        main {
            resources {
                srcDirs = ["src/main/java"]
                includes = ["**/*.fxml"]
            }
        }
    }
     
    mainClassName = "compty.Main"
     
     
    repositories {
        mavenCentral()
        jcenter()
        google()
    //    flatDir {
    //        dirs 'bin/commons-io-2.7'
    //    }
    }
     
    dependencies {
        implementation 'org.apache.commons:commons-csv:1.8'
    //    implementation fileTree("$rootDir/bin/commons-io-2.7/commons-io-2.7.jar")
        implementation group: 'commons-io', name: 'commons-io', version: '2.8.0'
        implementation 'org.apache.commons:commons-lang3:3.11'
        implementation 'org.openjfx:javafx:16-ea+2'
    }
    Et sinon afin de mieux appréhender et comprendre la philosophie de Java pourriez me dire :
    • La declaration d'un chemin absolue (donc commencant par "/") commence à partir d'ou dans la structure du jar ?
    • Pourquoi le contenu de mon dossier src/main/java/compty/views se retrouve dans le JAR dans le dossier resources
    • les fichiers FXML doivent obligatoirement être considérés comme des resources ? Moi je préférerais les avoir dans un package de même niveau que controller
    • quel serait au final la structure hierarchique de code la plus normé ou conventionnelle pour une application JavaFX ?


    Merci de votre précieux éclairage.
    Images attachées Images attachées   

  2. #2
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Ça fait beaucoup de setLocation() quand même sachant que seule la dernière compte...

    Et sinon tu as une arborescence dans le style main / compty / controller ce qui te donne un package compty.controllerIl faut pas chercher midi a 14h pour comprendre ce que deviendra main / compty / views
    un package / répertoire compty.views


    Vu que tu es dans le package controller, il te faut prendre les chemins absolus complet en partant de la racine donc ici /compty/views/MonFXML.fxml. Et sinon les chemins relatifs (../views/MonFXML.fxml) ça marche aussi...
    Après le plus simple si tu es pas sur de ton coup est de tester si les URLs retournées sont null ou pas.

    Nom : gradle1.jpg
Affichages : 748
Taille : 88,6 Ko

    Y a pas de sous-répertoire main dans mon exemple mais bon au final c'est pareil...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    package test;
     
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
     
    public final class Main extends Application {
     
        public static void main(String...args) {
            launch(args);
        }
     
        @Override
        public void start(Stage primaryStage) throws Exception {
            final var loader = new FXMLLoader(getClass().getResource("views/MainUI.fxml"));
            final var root = loader.<Parent>load();
            final var scene = new Scene(root);
            primaryStage.setTitle("Test");
            primaryStage.setWidth(1000);
            primaryStage.setHeight(800);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    package test.controllers;
     
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.fxml.Initializable;
    import javafx.scene.Node;
    import javafx.scene.layout.BorderPane;
    import test.Main;
     
    import java.io.IOException;
    import java.net.URL;
    import java.util.ResourceBundle;
     
    public final class MainUIController implements Initializable {
        @FXML
        private BorderPane root;
     
        @Override
        public void initialize(URL location, ResourceBundle resources) {
            // Avec la classe Main.
            System.out.println(Main.class.getResource("/test/views/Top.fxml"));
            System.out.println(getClass().getResource("/test/views/Bottom.fxml"));
            // Avec notre propre classe.
            System.out.println(getClass().getResource("../views/Right.fxml"));
            System.out.println(getClass().getResource("../views/Left.fxml"));
            System.out.println(getClass().getResource("../views/Center.fxml"));
            try {
                final var loader1 = new FXMLLoader();
                loader1.setLocation(Main.class.getResource("/test/views/Top.fxml"));
                root.setTop(loader1.<Node>load());
                final var loader2 = new FXMLLoader();
                loader2.setLocation(getClass().getResource("/test/views/Bottom.fxml"));
                root.setBottom(loader2.<Node>load());
                final var loader3 = new FXMLLoader();
                loader3.setLocation(getClass().getResource("../views/Right.fxml"));
                root.setRight(loader3.<Node>load());
                final var loader4 = new FXMLLoader();
                loader4.setLocation(getClass().getResource("../views/Left.fxml"));
                root.setLeft(loader4.<Node>load());
                final var loader5 = new FXMLLoader(getClass().getResource("../views/Center.fxml"));
                root.setCenter(loader5.<Node>load());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <?xml version="1.0" encoding="UTF-8"?>
     
    <?import javafx.scene.layout.BorderPane?>
     
    <BorderPane fx:id="root" xmlns:fx="http://javafx.com/fxml" fx:controller="test.controllers.MainUIController" >
     
    </BorderPane>
    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <?xml version="1.0" encoding="UTF-8"?>
     
    <?import javafx.scene.layout.Region?>
     
    <Region id="bottom" xmlns:fx="http://javafx.com/fxml" style="-fx-background-color: red;" minHeight="30">
     
    </Region>
    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <?xml version="1.0" encoding="UTF-8"?>
     
    <?import javafx.scene.layout.Region?>
     
    <Region id="center" xmlns:fx="http://javafx.com/fxml" style="-fx-background-color: yellow;" minHeight="30" minWidth="30">
     
    </Region>
    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <?xml version="1.0" encoding="UTF-8"?>
     
    <?import javafx.scene.layout.Region?>
     
    <Region id="left" xmlns:fx="http://javafx.com/fxml" style="-fx-background-color: gray;" minWidth="30">
     
    </Region>
    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <?xml version="1.0" encoding="UTF-8"?>
     
    <?import javafx.scene.layout.Region?>
     
    <Region id="right" xmlns:fx="http://javafx.com/fxml" style="-fx-background-color: green;" minWidth="30">
     
    </Region>
    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <?xml version="1.0" encoding="UTF-8"?>
     
    <?import javafx.scene.layout.Region?>
     
    <Region id="top" xmlns:fx="http://javafx.com/fxml" style="-fx-background-color: blue;" minHeight="30">
     
    </Region>

    Nom : gradle2.jpg
Affichages : 742
Taille : 45,9 Ko

    Après, si ton UI est statique, quel interret de la monter dynamiquement ? Pourquoi ne pas inclure directement les FXML les uns dans les autres sachant que tu pourras quand même recuperer des references vers les sous-controllers.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  3. #3
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Pour le reste :
    1. / c'est la racine (du JAR / module actuel) ça permet donc de définir un chemin complet qui part de la racine. quand ca commence pas par /, c'est un chemin relatif par rapport au package courant (donc en général un sous-package plus bas dans l’arborescence). Et ../ c'est pour remonter au niveau supérieur. Bref ça marche comme une arborescence Unix étrangement
    2. Pourquoi le contenu de mon dossier src/main/java/compty/views se retrouve dans le JAR dans le dossier resources
      Hum ? On a des répertoires nommés a l'identique mais stocké dans des chemins différents pour faciliter le développement ainsi que la vue dans l'IDE et bien distinguer le code des ressources (sinon ça fait un gros bazar avec plein de fichiers quand on met tout ensemble dans un gros projet) mais c'est tout artificiel. Tout sera réuni en une seule et unique arborescence quand tout sera assemblés dans un fichier JAR. Ça permet de faciliter la découverte des ressources sur le CLASSPATH (une notion de Java) via getClass().getResource().

      Par contre j'aurais bien aime savoir ou se trouvait le fichier CSS pour finir a cet endroit.

      Faudrait peut-etre ouvrir le JAR dans un utilitaire ZIP pour voir ce a quoi il ressemble car c'est peut-etre encore l'IDE qui joue des tours ici.
    3. C'est le template de ton projet Gradle qui veut ça. Dans mes projets (pas cet exemple de test) je les mets dans le même package même si je garde la distinction entre code et ressources dans l'IDE.
    4. Y en a pas vraiment. Gluon a tendance a faire ce que tu as la (package controller, package views, package css). Moi j'ai plutôt des packages scene.<nom du controle> pour les contrôles graphiques, écrans ou boites de dialogue que je crée.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  4. #4
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2015
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2015
    Messages : 76
    Points : 58
    Points
    58
    Par défaut
    Merci Bouye pour ces explications très détaillés

    J'ai pu trouver et comprendre quelle ligne de chargement de FXML utiliser.

    Mais le vraiment problème n'était pas en soit le chargement d'un FXML (puisque parmi tout mes essais j'avais trouvé malgré moi la bonne façon de déclarer l'URL) mais plutôt l'insertion des nodes du FXML chargé dans celui déjà existant. Cela me génère encore aujourd'hui une erreur que je ne comprend pas et Java traduit cela comme une erreur de chargement alors que c'est plutôt une erreur d'insertion.

    Pour tout te dire je ne sais pas encore réellement quel solution me conviendra le mieux pour mon application au niveau de la philosophie de chargement de l'UI.
    Mais j'ai vu une solution sur internet qui avait leur intéressante pour éviter de concevoir son UI uniquement par des enchainements de scene. D’où le fait de vouloir créer des chargements dynamiques. Mais je suis pas encore sûr de moi. Je suis en phase d'essai

    Mon fichier CSS se trouve actuellement ici : src/main/resources/css/main.css (le placement de celui-ci est encore approximatif).

  5. #5
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Il faudrait créer et fournir un projet simple de test démontrant ce soucis.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  6. #6
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2015
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2015
    Messages : 76
    Points : 58
    Points
    58
    Par défaut
    Pour moi il s'agissait finalement d'un autre problème et je ne voulais pas vous embêter avec cela avant d'avoir réellement chercher de mon coté. Chose que je n'ai pas encore complètement fait. Je ne me considère pas bloqué mais juste besoin d'un peu de temps pour me focaliser sur le sujet. Et donc poser aussi des questions plus précises pour mieux comprendre.

    Alors que pour la problématique des URLs, j'étais vraiment bloqué et ne savait pas vraiment quel était la solution à utiliser et pourquoi.

    Vous m'avez pour le moment très bien aidé avec une réponse plus que qualitative et je vous en remercie beaucoup

Discussions similaires

  1. chargement d'une matrice *.m dans un uitable
    Par Gouasmi_moh dans le forum Interfaces Graphiques
    Réponses: 3
    Dernier message: 17/03/2011, 16h10
  2. chargement d'une ligne datatable dans une modelpanel
    Par cyclopsnet dans le forum JSF
    Réponses: 3
    Dernier message: 13/10/2010, 18h26
  3. [GD] Afficher une "resource" image dans un navigateur
    Par AceEye dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 18/03/2010, 10h59
  4. Detection du chargement d'une nouvelle page dans Firefox
    Par meric dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 05/09/2008, 16h02
  5. [JAR] Accéder à une resource contenue dans un jar
    Par Blo0d4x3 dans le forum Général Java
    Réponses: 4
    Dernier message: 17/02/2006, 08h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo