2017-08-22 3 views
1

Je suis nouveau dans FXML et j'ai beaucoup cherché pour trouver une solution à mes problèmes avec TabPanes. Dans l'exemple ci-dessous (basé sur l'exemple de JavaFX: Adding a new tab from a tab controller), je souhaite ajouter des onglets à un TapPane - l'ajout d'un nouvel onglet à l'intérieur d'un onglet "inclus" (Tab 1) ne pose pas de problème, mais lorsque j'essaie d'ajouter un onglet de l'intérieur d'un onglet créé dynamiquement (par exemple Tab 2), je reçois toujours une exception NullPointerException. Quelqu'un pourrait-il me dire comment accéder au FirstTab-Controller depuis l'onglet créé dynamiquement (Tab 2)?Accéder TabPane à partir d'un onglet ajouté dynamiquement

TestingTabPane.java:

package testingtabs; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 


public class TestingTabPane extends Application { 

    @Override 
    public void start(Stage stage) throws Exception { 
     Parent root = FXMLLoader.load(getClass().getResource("FirstTab.fxml")); 

     Scene scene = new Scene(root); 

     stage.setScene(scene); 
     stage.show(); 
    } 

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

} 

FirstTab.fxml:

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

<?import java.lang.*?> 
<?import java.util.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 

<TabPane fx:id="myTabPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" tabClosingPolicy="UNAVAILABLE" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="testingtabs.FirstTabController"> 
    <tabs> 
    <Tab fx:id="FirstTab" text="Tab 1"> 
     <fx:include source="NewTab.fxml" fx:id="newTab"/> 
    </Tab> 
    </tabs> 
</TabPane> 

FirstTabController.java:

package testingtabs; 

import java.io.IOException; 
import javafx.fxml.FXML; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.control.Tab; 
import javafx.scene.control.TabPane; 

public class FirstTabController { 

    @FXML 
    public TabPane myTabPane; 

    @FXML 
    public NewTabController newTabController; 

    public void initialize() { 
     newTabController.setMainWindowController(this); 
    } 

    public void createTab() throws IOException { 
     int numTabs = myTabPane.getTabs().size(); 
     Tab tab = new Tab("Tab " + (numTabs + 1)); 
     Parent root = FXMLLoader.load(getClass().getResource("NewTab.fxml")); 
     tab.setContent(root); 
     myTabPane.getTabs().add(tab); 

    } 
} 

NewTab.fxml:

<?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/8" fx:controller="testingtabs.NewTabController"> 
    <children> 
     <Button fx:id="addTabBtn" layoutX="268.0" layoutY="187.0" mnemonicParsing="false" onAction="#onAddTabBtnClicked" text="add tab" /> 
    </children> 
</AnchorPane> 

NewTabController.java:

package testingtabs; 

import java.io.IOException; 
import javafx.fxml.FXML; 

public class NewTabController { 

    private FirstTabController firstTabController ; 

    public void setMainWindowController(FirstTabController mainWindowController) { 
     this.firstTabController = mainWindowController ; 
    } 

    @FXML 
    public void onAddTabBtnClicked() throws IOException { 
     firstTabController.createTab(); 
    } 
} 

Répondre

1

Lorsque vous chargez un onglet « dynamique » par la méthode createTab(), vous n'appelez setMainWindowController(...) sur le contrôleur pour que le contenu de l'onglet nouvellement créé. Donc, dans ce contrôleur, firstTabController est toujours null, et vous obtenez une exception Null Pointer dans la méthode onAddTabBtnClicked.

Vous pouvez faire

public void createTab() throws IOException { 
    int numTabs = myTabPane.getTabs().size(); 
    Tab tab = new Tab("Tab " + (numTabs + 1)); 
    FXMLLoader loader = new FXMLLoader(getClass().getResource("NewTab.fxml")); 
    Parent root = loader.load(); 
    NewTabController newTabController = loader.getController(); 
    newTabController.setMainWindowController(this); 
    tab.setContent(root); 
    myTabPane.getTabs().add(tab); 
} 

Vous n'avez pas vraiment besoin de traiter le premier onglet différemment aux autres; vous pouvez simplement appeler la méthode createTab() de initialize() pour faire le premier, ce qui réduit un peu le code (et en utilisant des techniques cohérentes tout au long):

FirstTab.fxml:

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

<?import java.lang.*?> 
<?import java.util.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 

<TabPane fx:id="myTabPane" maxHeight="-Infinity" maxWidth="-Infinity" 
    minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" 
    prefWidth="600.0" tabClosingPolicy="UNAVAILABLE" 
    xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" 
    fx:controller="testingtabs.FirstTabController" /> 

FirstTabController:

package testingtabs; 

import java.io.IOException; 
import javafx.fxml.FXML; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.control.Tab; 
import javafx.scene.control.TabPane; 

public class FirstTabController { 

    @FXML 
    public TabPane myTabPane; 

    public void initialize() { 
     createTab(); 
    } 

    public void createTab() throws IOException { 
     int numTabs = myTabPane.getTabs().size(); 
     Tab tab = new Tab("Tab " + (numTabs + 1)); 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("NewTab.fxml")); 
     Parent root = loader.load(); 
     NewTabController newTabController = loader.getController(); 
     newTabController.setMainWindowController(this); 
     tab.setContent(root); 
     myTabPane.getTabs().add(tab); 
    } 
} 

NewTab.fxml et NewTabController restent les mêmes.

+0

Ouf! - Merci beaucoup pour la réponse détaillée, James_D - fonctionne très bien :) J'ai passé environ une semaine avec le problème, essayé beaucoup et me suis retrouvé dans un grand bordel, enfin;) - votre solution m'aide beaucoup :) – Guenter