2017-08-06 4 views
0

Je crois que la seule chose différente avec ceci est la version de SceneBuilder est 8.3 et je me sers TreeTableView et TreeTableColumn avec Oracle Java 8 Voici le FXMLjavafx8 FXMLLoader retourne null

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.control.TreeTableColumn?> 
<?import javafx.scene.control.TreeTableView?> 

<TreeTableView maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="1" minWidth="1" prefHeight="400.0" prefWidth="600.0" showRoot="false" stylesheets="@org/cornova/AudioExplorer.css" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.cornova.AudioExplorerController"> 
    <columns> 
    <TreeTableColumn fx:id="mixerName" editable="false" maxWidth="6000.0" minWidth="100.0" prefWidth="-1.0" text="Mixers" /> 
    <TreeTableColumn fx:id="lineNames" maxWidth="49.0" minWidth="100.0" prefWidth="-1.0" text="Lines" /> 
     <TreeTableColumn fx:id="controlNames" minWidth="100.0" prefWidth="-1.0" text="Controls" /> 
     <TreeTableColumn fx:id="formatsNames" minWidth="100.0" prefWidth="-1.0" text="Formats" /> 
    </columns> 
</TreeTableView> 

Voici la classe contrôleur

/** 
* Sample Skeleton for 'AudioExplorer.fxml' Controller Class 
*/ 

package org.cornova; 

import java.net.URL; 
import java.util.ResourceBundle; 
import javafx.fxml.FXML; 
import javafx.scene.control.TreeTableColumn; 

public class AudioExplorerController { 

    @FXML // ResourceBundle that was given to the FXMLLoader 
    private ResourceBundle resources; 

    @FXML // URL location of the FXML file that was given to the FXMLLoader 
    private URL location; 

    @FXML // fx:id="mixerName" 
    private TreeTableColumn<?, ?> mixerName; // Value injected by FXMLLoader 

    @FXML // fx:id="lineNames" 
    private TreeTableColumn<?, ?> lineNames; // Value injected by FXMLLoader 

    @FXML // fx:id="controlNames" 
    private TreeTableColumn<?, ?> controlNames; // Value injected by FXMLLoader 

    @FXML // fx:id="formatsNames" 
    private TreeTableColumn<?, ?> formatsNames; // Value injected by FXMLLoader 

    @FXML // This method is called by the FXMLLoader when initialization is complete 
    void initialize() { 
     assert mixerName != null : "fx:id=\"mixerName\" was not injected: check your FXML file 'AudioExplorer.fxml'."; 
     assert lineNames != null : "fx:id=\"lineNames\" was not injected: check your FXML file 'AudioExplorer.fxml'."; 
     assert controlNames != null : "fx:id=\"controlNames\" was not injected: check your FXML file 'AudioExplorer.fxml'."; 
     assert formatsNames != null : "fx:id=\"formatsNames\" was not injected: check your FXML file 'AudioExplorer.fxml'."; 

    } 
} 

Voici la classe principale

package org.cornova; 

import java.net.URL; 
import javafx.application.Application; 
import javafx.beans.property.ReadOnlyStringWrapper; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.control.TreeTableColumn.CellDataFeatures; 
import javafx.scene.control.TreeItem; 
import javafx.scene.control.TreeTableColumn; 
import javafx.scene.control.TreeTableView; 
import javafx.stage.Stage; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.Mixer; 
import javax.sound.sampled.Mixer.Info; 

/** 
* 
* @author walt 
*/ 
public class AudioExplorer extends Application { 

    private URL url; 
    private FXMLLoader explorerLoader; 
    private AudioExplorerController audioController; 

    @Override 
    public void start(Stage stage) throws Exception { 
     stage.setTitle("Audio Explorer"); 
     final Scene scene = new Scene(new Group(), 200, 400); 
     Group sceneRoot = (Group)scene.getRoot(); 
     try { 
      url = getClass().getResource("/AudioExplorer.fxml"); 
      explorerLoader = new FXMLLoader(url); 
      explorerLoader.setLocation(url); 
      audioController = explorerLoader.getController(); 
     } catch (Exception e) { 
      System.out.println(e); 
     }  
     //Creating the root element 
     TreeItem rootNode = new TreeItem(); 
     rootNode.setExpanded(true); 
     Info mixers[] = AudioSystem.getMixerInfo(); 
     rootNode = new TreeItem<>(mixers[0]); 
     //Creating tree items 
     for (int i = 0; i < mixers.length; i++) { 
      rootNode.getChildren().add(new TreeItem<>(mixers[i])); 
     } 

     //Creating a column 
     TreeTableColumn<Info,String> mixerInfo = new TreeTableColumn<>("Mixers"); 
     mixerInfo.setMaxWidth(1500); 

     //Defining cell content 
     mixerInfo.setCellValueFactory((CellDataFeatures<Info, String> p) -> 
      new ReadOnlyStringWrapper(p.getValue().getValue().getName())); 

     //Creating a tree table view 
     final TreeTableView<Info> treeTableView = new TreeTableView<>(rootNode); 
     treeTableView.getColumns().add(mixerInfo); 
     treeTableView.setMaxWidth(1500); 
     treeTableView.setShowRoot(false); 
     treeTableView.autosize(); 
     sceneRoot.getChildren().add(treeTableView); 
     stage.setScene(scene); 
     stage.show();  
    } 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     launch(args); 
    } 

} 

Tout cela est fait sous Netbeans 8.2. Je l'ai fait, peut-être une douzaine de ces applications graphiques basées sur des constructeurs de scène peut-être il y a 18 mois. Une chose que j'ai découverte à l'époque était de m'assurer que l'emplacement de la source css et du contrôleur était ajusté pour l'espace de nom dans lequel ils seraient, ce qui est reflété dans le fxml.

Le fichier css est vide car je l'ai seulement défini dans SceneBuilder à ce stade, c'est pourquoi je ne l'ai pas inclus (seulement les commentaires).

Je pense que je me souviens de quand je commençais avec SceneBuilder, c'est qu'il est tentant d'échouer silencieusement. Tnanks!

+0

Vous devez appeler 'FXMLLoader # load' pour le chargeur pour créer et alimenter le contrôleur. – Itai

Répondre

1

Vous avez en fait besoin de charger le fxml pour que le contrôleur soit créé sur la base du fxml. passant également l'emplacement est deux fois pas nécessaire:

url = getClass().getResource("/AudioExplorer.fxml"); 
explorerLoader = new FXMLLoader(url); 

try { 
    TreeTableView<?> audioExplorer = explorerLoader.load(); 
    audioController = explorerLoader.getController(); 
    ... 
} catch ... 

De plus, il y a peu de raisons de conserver une référence à l'instance FXMLLoader dans un champ. Une fois que vous avez terminé le chargement, extrayez simplement les informations dont vous avez besoin et "laissez tomber" la référence du chargeur. L'appel load une seconde fois doit être évité ... de toute façon

+0

Merci fabian! Vous avez raison au deuxième chargement et définissez l'emplacement de l'URL deux fois. Il s'est avéré que j'avais, dans beaucoup de mes autres contrôles fait une charge du contrôle parent ... mais pas universellement. C'est ce qui est étrange. Tnx agn. –

0

En plus de la réponse de fabian, s'il vous plaît noter que je l'ai écrit quelques utility methods, ce qui peut réduire FXML chargement à une seule déclaration, tels que:

TreeTableView<?> audioExplorer = FXMLLoaders.load(AudioExplorer.class); 

S'il vous plaît noter, ce n'est possible que, si vous vous en tenez à la convention de dénomination suivante:

Si une classe "mypackage < nom>." charge un fichier FXML, le FXML fichier devrait être dans le même paquet et être nommé "< nom>.fxml".

La bibliothèque est Open Source. Peut-être qu'elle vous sera utile:

<dependency> 
    <groupId>org.drombler.commons</groupId> 
    <artifactId>drombler-commons-fx-core</artifactId> 
    <version>0.10</version> 
</dependency> 

Vous pouvez en lire davantage ici: http://puces-blog.blogspot.ch/2015/03/drombler-commons-conventions-to.html

+0

Bonne info à connaître ... merci du partage Puce! –