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 :

[FXML] Se passer des Panel


Sujet :

JavaFX

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 7
    Par défaut [FXML] Se passer des Panel
    Bonjour

    Je viens tous juste de débuter sur JavaFX. Je doit dire que c'est très bien. Mais sa change radicalement de Swing ... Du coup je suis en apprentissage dans ce domaine.

    Je suis chargé de développer une nouvelle version d'un programme modulaire. C'est à dire qu'on l'on a un coeur (appelé Core). Il contient une interface sommaire et de nombreux services (persistance, logger, l'insertion des modules, la fermeture du programme, etc ...).
    Lorsqu'on l'on utilise Swing et que l'on fournit un module, il passe un JPanel au Coeur qui se charge de le placer dans un JTabPanel. Nous souhaitons garder cette façon de faire car cela éviterai de devoir à reprogrammer les modules. D'autant plus que nos clients ont parfois leur propres modules.


    Je suis parvenu "sans trop de mal" a reprogrammer l'interface du Core en FXML (et comme je suis fainéant, j'utilise JavaFX Scene Builder). Ce que je n'ai pas encore compris, c'est comment passer les Panel des modules ?
    Je pense qu'il faut les encapsuler dans des Scene et trouver un moyen de l'insérer dans le TabPane du Core ? Quel serai alors la fonction magique ? Et l'interface garderai-t-elle un lien avec le module au travers de l'objet Scene et du Controller associé ?

    Bien à vous
    Thomas

  2. #2
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 897
    Billets dans le blog
    54
    Par défaut
    Vu qu'on a pas tous les détails notamment sur comment sont architecturés/codés tes modules ou comment tu les charges, je vais donner des indications au sens large.

    J'imagine que les modules sont eux-mêmes des FXML définis séparément ou des nœuds/régions/contrôles du SceneGraph codés a mano ou une combinaison* des deux (noeud étendant région + skin FXML + contrôleur). Dans ce cas, ils n'ont pas besoin d’être attachés a des scènes séparées, ils vont être injectés dans le TabPane du Core. C'est la classe contrôleur du Core qui va s'en charger si tu as un contrôleur pour cet objet ou alors la classe qui le manipule.

    Si tu manipules directement les FXML des modules, c'est le noeud racine qui sera injecté (généralement un AnchorPane, mais tu peux utiliser n'importe quoi en racine d'un FXML en fait) et tu peux récupérer une référence sur son contrôleur au chargement via FXMLLoader. Tu peux aussi injecter toi-même un contrôleur dans un FXML (pas trop testé).

    Si tu manipules un nœuds qui encapsule/cache tout, c'est ce nœud-là qui sera injecté dans le TabPane .

    *Voir : Creating a reusable JavaFX custom control..
    Donc tu peux très bien te définir une classe abstraite commune a tous les modules qui soit un noeud graphique, et avoir une classe concrète publique qui hérite du module abstrait, un FXML et un contrôleur privé pour chaque module.

    EDIT - ah oui, il y a aussi la construction de type <fx:root type=... qui permet de spécifier, directement depuis le FXML, une classe noeud dans laquelle le contenu du FXML va être ajoutée, mais je n'ai pas encore testé comment cela fonctionne.
    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
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 7
    Par défaut
    Merci pour votre réponse. Je comprend beaucoup mieux la chose. Cela éclaircit et confirme ce que j'avais imaginé.

    Pour l'architecture des modules, c'est fort simple :
    Le Core trouve les modules dans un fichier tous les modules à charger. Il détermine si c'est un module grâce au manifest.mf. Il charge alors une classe implémentant une interface où il y a toutes les fonctions nécessaires à faire des échanges de donnée (initié par le Core) entre le Core et le module. Il y a notamment une fonction chargée de donner une vue qui en version Swing fournit un JPanel.

    Je pense que le mieux est que cette fonction ne fournisse plus un JPanel, mais donc le noeud racine de la vue du module. Le core pourra donc récupérer ce noeud et l'ajouter au TabPane par l'intermédiaire du contrôleur.
    Je ne pense pas utiliser la "balise" (c'est le bon terme ?) "<fx:root type=..." car (toujours si j'ai bien compris) la vue principale vient à changer de nom (pour x raisons), cela ne fonctionnerai plus.

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 7
    Par défaut
    Bonjour

    J'ai bien avancé dans mon problème (définition des interface en FXML avec JavaFX Scene Builder). J'ai intégré une interface dans un module pour réaliser un test. Je bute sur un second problème.

    Le core reconnait bien le module grâce à son manifest.mf. Il le charge également correctement (comme avec la version Swing). Le problème est qu'il ne trouve pas le contrôleur alors qu'il existe à l'emplacement qu'il attend. Il parvient toutefois fois a obtenir le noeud et l'ajouter dans le TabPane, mais celui-ci est vierge ... (et pour cause : il est null)


    La console :
    Executing Launcher from C:\Users\blablabla\Core\dist\run1301399881\Core.jar using platform C:\Program Files\Java\jdk1.7.0_25/bin/java

    Chargement des modules
    Database OK

    java.lang.ClassNotFoundException: module.vue.PanelController
    file:/C:/Users/blablabla/Core/modules/dist/Persistance.jar!/module/vue/Panel.fxml:10
    at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:726)
    at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:775)
    at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:180)
    at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:563)
    at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2314)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2131)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2028)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2744)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2723)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2709)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2696)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2685)
    at module.vue.Vue.initFenetre(Vue.java:29)
    at
    module.module.Module.plug(Module.java:37)
    at module.ModuleManager.plug(ModuleManager.java:32)
    at module.ModuleManager.init(ModuleManager.java:26)
    at core.Core.start(Core.java:51)
    (à noter que le "database OK" indique seulement le chargement du module et non son initialisation complète).

    Voici l'initialisation de l'interface :
    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
     
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package module.vue;
     
    import java.io.IOException;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Node;
     
    /**
     *
     * @author auriel
     */
    public class Vue {
        private static Vue instance = new Vue();
     
        public static Vue getInstance(){
            return instance;
        }
     
        ////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////
     
        private Node node;
     
        public void initFenetre() throws IOException{
            node = FXMLLoader.load(getClass().getResource("Panel.fxml"));
        }
     
        public Node getNode() {
            return node;
        }
    }

    Voici le PanelController en question
    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
     
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package module.vue;
     
    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Button;
    import javafx.scene.control.CheckBox;
    import javafx.scene.control.Label;
    import javafx.scene.control.TextField;
     
    /**
     * FXML Controller class
     *
     * @author auriel
     */
    public class PanelController implements Initializable {
     
        @FXML
        private TextField textFieldSearch;
        @FXML
        private Button buttonFind;
        @FXML
        private Button buttonSearch;
     
        @FXML
        private TextField textFieldPathDatabase;
        @FXML
        private Button buttonRestart;
     
        @FXML
        private CheckBox checkBoxAutoClear;
        @FXML
        private TextField textFieldDelayClear;
     
        @FXML
        private Button buttonClearAll;
     
        //Information
        @FXML
        private Label labelTextNumber;
        @FXML
        private Label labelKeywordNumber;
        @FXML
        private Label labelAuthorNumber;
        @FXML
        private Label labelLinkNumber;
        /**
         * Initializes the controller class.
         */
        @Override
        public void initialize(URL url, ResourceBundle rb) {
            // TODO
        }    
     
        @FXML
        private void textFieldSearchAction(ActionEvent event) {
        }
     
        @FXML
        private void buttonSearchAction(ActionEvent event) {
        }
     
        @FXML
        private void buttonFindAction(ActionEvent event) {
        }
     
        @FXML
        private void checkBoxAutoClearAction(ActionEvent event) {
        }
     
        @FXML
        private void textFieldPathDatabaseAction(ActionEvent event) {
        }
     
        @FXML
        private void textFieldDelayClearAction(ActionEvent event) {
        }
     
        @FXML
        private void buttonClearAllAction(ActionEvent event) {
        }
    }

    Je ne sais absolument pas qu'elle est la cause de cette erreur. Je n'ai pas de problème avec le Core qui fonctionne très bien.
    Y a-t-il un paramètre à fournir au compilateur ?

    J'utilise NetBeans. Celui-ci comporte déjà un bug sur le manifest.mf au moment de la compilation (il ne prend pas en comte le manifest.mf déjà existant. Il faut donc le recréer dans un script à la compilation).

  5. #5
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 897
    Billets dans le blog
    54
    Par défaut
    Hum, c'est la journée des bugs bizarres.

    Ça n'influera probablement pas sur le résultat mais au lieu d'utiliser FXMLLoader.load(...), cree une nouvelle instance et appelle la méthode load() de cette instance. Richard Bair le chef architecte de l’équipe de JavaFX a plusieurs fois indiqué que la méthode statique fonctionne de manière "spéciale" ou n'est pas performante. De plus, avoir une référence sur le loader permet aussi de récupérer le contrôleur (enfin, quand son chargement ne plante pas).

    Citation Envoyé par https://wiki.openjdk.java.net/display/OpenJFX/Performance+Tips+and+Tricks
    • FXML
      • Proper use of FXMLLoader#load
        • The load() method of FXML loader is a tricky method. Make sure you are not calling the static one. The next code is wrong – it calls static method load() which has nothing common with your fxmlLoader object:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    FXMLLoader fxmlLoader = new FXMLLoader(); 
    Parent obj = fxmlLoader.load(getClass().getResource("MyApp.fxml")); 
    Object invalidController = fxmlLoader.getController();
    Correct way:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MyApp.fxml")); 
    Object obj = fxmlLoader.load(); 
    Object myController = fxmlLoader.getController();
    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
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 7
    Par défaut
    Bonjour

    Après des tests, la même erreur apparait. Voici mon code modifié :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        public void initFenetre() throws IOException{
            //node = FXMLLoader.load(getClass().getResource("Panel.fxml"));
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Panel.fxml")); 
            Object obj  =  fxmlLoader.load();
            System.out.println(obj.getClass().toString());
            node = (Node) obj; 
            controller = fxmlLoader.getController();
        }
    L'erreur se déclenche à la ligne : Object obj = fxmlLoader.load();

  7. #7
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 897
    Billets dans le blog
    54
    Par défaut
    Strange, on va reprendre les bases avec un test project :

    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
    package test;
     
    import java.net.URL;
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Node;
    import javafx.scene.Scene;
    import javafx.scene.layout.AnchorPane;
    import javafx.stage.Stage;
     
    /**
     */
    public class Main extends Application {
        @Override
        public void start(Stage stage) throws Exception {
            final String fileName="Test.fxml";   
            final URL fxmlURL = getClass().getResource(fileName);
            final FXMLLoader fxmlLoader = new FXMLLoader(fxmlURL);
            Node node = (Node) fxmlLoader.load();
            TestController controller = (TestController)fxmlLoader.getController();
            AnchorPane.setTopAnchor(node, 0d);
            AnchorPane.setLeftAnchor(node, 0d);
            AnchorPane.setBottomAnchor(node, 0d);
            AnchorPane.setRightAnchor(node, 0d);
            AnchorPane root = new AnchorPane();
            root.getChildren().add(node);
            Scene scene = new Scene(root);
            stage.setTitle("FXML");
            stage.setScene(scene);
            stage.show();
        }
     
        public static void main(String[] args) {
            launch(args);
        }
    }
    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
    package test;
     
    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Label;
     
    /**
     * FXML Controller class
     */
    public final class TestController implements Initializable {
     
        @FXML
        private Label label;
     
        /**
         * Initializes the controller class.
         */
        @Override
        public void initialize(URL url, ResourceBundle rb) {
            label.setText("Hello world!");
        }
    }
    FXML SceneBuilder 1.0
    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?xml version="1.0" encoding="UTF-8"?>
     
    <?import java.lang.*?>
    <?import java.util.*?>
    <?import javafx.scene.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
     
    <AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml" fx:controller="test.TestController">
      <children>
        <Label fx:id="label" layoutX="14.0" layoutY="6.0" text="Label" />
      </children>
    </AnchorPane>

    FXML SceneBuilder 1.1 final
    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?xml version="1.0" encoding="UTF-8"?>
     
    <?import java.lang.*?>
    <?import java.util.*?>
    <?import javafx.scene.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
     
    <AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="test.TestController">
      <children>
        <Label fx:id="label" layoutX="14.0" layoutY="6.0" text="Label" />
      </children>
    </AnchorPane>

    Architecture du projet :
    Nom : Untitled.png
Affichages : 1070
Taille : 125,9 Ko

    Vérifie donc que tes architectures sont similaires a ceci, que la classe du contrôleur soit dans le bon package, soit accessible (publique), etc.
    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

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 7
    Par défaut
    Bonjour

    Il y a effectivement un problème au niveau de du fichier FXML. Je n'avais pas ouvert les fichiers générés par Scene Builder et c'est au niveau d'une de ces balises.

    Il reconnait pas la balise fx:controller="nom d'une classe". Par contre il reconnait les fx:on[NomDUnEvent]="nom d'une fonction". Devrais-je en passer par là ? Où JavaFx est-il mal installé/paramétré ou alors c'est NetBeans ?

  9. #9
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 897
    Billets dans le blog
    54
    Par défaut
    NetBeans me souligne également fx:controller lorsque le FXML est au format SceneBuilder 1.1 (voir la différence dans les deux code postés au dessus) mais aucun soucis pour les charger tant en Java 7 qu'en Java 8.
    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

Discussions similaires

  1. Faire passer des composants par dessus un Panel
    Par Aloneghost dans le forum Composants VCL
    Réponses: 0
    Dernier message: 16/03/2009, 01h28
  2. problème our passer des string dans tableau d'int
    Par Battosaiii dans le forum C++
    Réponses: 9
    Dernier message: 15/07/2004, 17h42
  3. Réponses: 5
    Dernier message: 08/03/2004, 10h28
  4. Passer des Image avec SOAP
    Par pef421 dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 01/03/2004, 21h32
  5. [CR7][VB6] Passer des infos de Vb vers CR
    Par tripper.dim dans le forum SDK
    Réponses: 2
    Dernier message: 13/11/2003, 13h30

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