JavaFX jak załadować Tab w fxml w TabPane w fxml.

0

Witam. Mam pewien problem który mnie przerasta. Mianowicie mam aplikację w której:

>loguję się
>pojawia się główne okno aplikacji (mainWindow.fxml)
>wchodzę w file --> new --> new E-mail
>pojawia się okno w którym na razie nic nie działa oprócz przycisku finish
>klikam przycisk finisch 
>w TabPane powinna pojawić się nowa zawartość 
>BŁĄD java.lang.reflect.InvocationTargetException, Caused by: java.lang.NullPointerException

DODAM JESZCZE, ŻE WSZYSTKO DZIAŁA JEŚLI ŁADOWANIE ZAWARTOŚCI TABPANE ZROBI SIĘ NP. W METODZIE EXIT() CZYLI W SAMYM MENUITEM ZAMIAST W DODATKOWYM OKNIE.

Cały błąd:

"D:\Program Files\Programs\Java\jdk-9.0.4\bin\java.exe" "-javaagent:D:\Program Files\Programs\JetBrains\IntelliJ IDEA Community Edition 2018.2.3\lib\idea_rt.jar=59681:D:\Program Files\Programs\JetBrains\IntelliJ IDEA Community Edition 2018.2.3\bin" -Dfile.encoding=UTF-8 -classpath "D:\Program Files\CommonFiles\Emailator9\out\production\Emailator9" res.loginWindow.LoginController
ZALOGOWANO!!!
HELP CLICKED!!
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
	at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1787)
	at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1670)
	at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
	at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
	at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8863)
	at javafx.controls/javafx.scene.control.Button.fire(Button.java:200)
	at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:206)
	at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
	at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
	at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
	at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
	at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3876)
	at javafx.graphics/javafx.scene.Scene$MouseHandler.access$1300(Scene.java:3604)
	at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1874)
	at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2613)
	at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397)
	at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:434)
	at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
	at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433)
	at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556)
	at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942)
	at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
	at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175)
	at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
	at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275)
	at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
	at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1782)
	... 47 more
Caused by: java.lang.NullPointerException
	at res.mainWindow.mainWindow.MainController.finishButtonClicked(MainController.java:91)
	... 58 more

Process finished with exit code 0

mainWindow.fxml

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

<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.SeparatorMenuItem?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>

<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="720.0" prefWidth="1280.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="res.mainWindow.mainWindow.MainController">
    <children>
        <MenuBar>
            <menus>
                <Menu mnemonicParsing="false" text="File">
                    <items>
                        <Menu mnemonicParsing="false" text="New">
                            <items>
                                <MenuItem fx:id="emailItem" mnemonicParsing="false" onAction="#openCreateEmail" text="E-mail" />
                                <MenuItem mnemonicParsing="false" text="Auto E-mail" />
                            </items>
                        </Menu>
                        <SeparatorMenuItem mnemonicParsing="false" />
                        <MenuItem mnemonicParsing="false" text="Save" />
                        <MenuItem mnemonicParsing="false" text="Save as" />
                        <SeparatorMenuItem mnemonicParsing="false" />
                        <MenuItem fx:id="exitItem" mnemonicParsing="false" onAction="#exit" text="Exit" />
                    </items>
                </Menu>
                <Menu mnemonicParsing="false" text="Edit">
                    <items>
                        <MenuItem mnemonicParsing="false" text="Delete" />
                    </items>
                </Menu>
                <Menu mnemonicParsing="false" text="Help">
                    <items>
                        <MenuItem mnemonicParsing="false" text="About" />
                    </items>
                </Menu>
            </menus>
        </MenuBar>
        <SplitPane dividerPositions="0.19248826291079812" prefHeight="697.0" prefWidth="1280.0" VBox.vgrow="ALWAYS">
            <items>
                <StackPane maxWidth="650.0" prefHeight="150.0" prefWidth="200.0">
                    <children>
                        <VBox prefHeight="200.0" prefWidth="100.0">
                            <children>
                                <StackPane>

                                </StackPane>
                            </children>
                        </VBox>
                    </children>
                </StackPane>
                <StackPane fx:id="rightStackPaneInSplitPane" prefHeight="150.0" prefWidth="200.0">
                    <children>
                        <TabPane fx:id="tabPane" prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE">
                            <tabs>
                                <Tab text="Untitled">
                                    <content>
                                        <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
                                    </content>
                                </Tab>
                            </tabs>
                        </TabPane>
                    </children>
                </StackPane>
            </items>
        </SplitPane>
    </children>
</VBox>

MainController.java:

package res.mainWindow.mainWindow;

import javafx.application.Platform;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class MainController
{
    private Stage creatingEmailStage = new Stage();
    private boolean isFirstCreatingEmail = false;

    @FXML
    private MenuItem emailItem;

    @FXML
    private MenuItem exitItem;

    @FXML
    private StackPane rightStackPaneInSplitPane;

    @FXML
    private AnchorPane anchorPane;

    @FXML
    private Button helpButton;

    @FXML
    private Button cancelButton;

    @FXML
    private Button finishButton;

    @FXML
    private TextField nameTextField;

    @FXML
    private TextField pathTextField;

    @FXML
    private TabPane tabPane;

    @FXML
    void openCreateEmail(Event event) throws Exception
    {
        //ten IF zapobiega bladowi powodowanemu przez dwukrotne ustawianie stylu
        if (isFirstCreatingEmail == false)
        {
            creatingEmailStage.initStyle(StageStyle.UTILITY);
            isFirstCreatingEmail = true;
        }
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(this.getClass().getResource("/res/mainWindow/createEmailWindow/createEmailWindow.fxml"));
        AnchorPane anchorPane = loader.load();
        Scene scene = new Scene(anchorPane);
        creatingEmailStage.setScene(scene);
        creatingEmailStage.setResizable(false);
        creatingEmailStage.show();
    }

    @FXML
    void cancelButtonClicked(MouseEvent event)
    {
        Stage stage = (Stage) cancelButton.getScene().getWindow();
        stage.close();
    }

    @FXML
    void helpButtonClicked(MouseEvent event)
    {
        System.out.println("HELP CLICKED!!");
    }

    @FXML
    public void exit(javafx.event.ActionEvent actionEvent) throws Exception
    {
        System.exit(0);
    }

    @FXML
    public void finishButtonClicked(javafx.event.ActionEvent actionEvent) throws Exception
    {
        tabPane.getTabs().remove(0);
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(this.getClass().getResource("/res/mainWindow/emailTab/emailTab.fxml"));
        Tab tab = loader.load();

        tabPane.getTabs().add(tab);
    }
}


emailTab.fxml :

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

<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.web.HTMLEditor?>

<Tab text="Untitled Tab" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="res.mainWindow.emailTab.EmailTabController">
    <AnchorPane>
        <children>
            <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity">
                <children>
                    <Label layoutX="10.0" layoutY="15.0" text="From:" />
                    <Label layoutX="10.0" layoutY="80.0" text="To:" />
                    <Label layoutX="10.0" layoutY="145.0" text="Topic:" />
                    <TextField layoutX="10.0" layoutY="40.0" prefHeight="25.0" prefWidth="380.0" />
                    <TextField layoutX="10.0" layoutY="105.0" prefHeight="25.0" prefWidth="380.0" />
                    <TextField layoutX="10.0" layoutY="170.0" prefHeight="25.0" prefWidth="380.0" />
                    <HTMLEditor htmlText="<html><head></head><body contenteditable="true"></body></html>" layoutX="10.0" layoutY="225.0" prefHeight="420.0" prefWidth="965.0" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="210.0" />
                </children>
            </AnchorPane>
        </children>
    </AnchorPane>
</Tab>

createEmailWindow.fxml

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>

<AnchorPane fx:id="anchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="res.mainWindow.mainWindow.MainController">
    <children>
        <Button fx:id="helpButton" layoutX="530.0" layoutY="360.0" mnemonicParsing="false" onMouseClicked="#helpButtonClicked" prefWidth="60.0" text="Help" AnchorPane.bottomAnchor="15.0" AnchorPane.rightAnchor="10.0" />
        <Button fx:id="cancelButton" layoutX="460.0" layoutY="360.0" mnemonicParsing="false" onMouseClicked="#cancelButtonClicked" prefWidth="60.0" text="Cancel" AnchorPane.bottomAnchor="15.0" AnchorPane.rightAnchor="80.0" />
        <Button fx:id="finishButton" layoutX="390.0" layoutY="360.0" mnemonicParsing="false" onAction="#finishButtonClicked" prefWidth="60.0" text="Finish" AnchorPane.bottomAnchor="15.0" AnchorPane.rightAnchor="150.0" />
        <Label layoutX="15.0" layoutY="15.0" text="Name:">
            <font>
                <Font size="13.0" />
            </font>
        </Label>
        <Label layoutX="15.0" layoutY="80.0" text="Path:">
            <font>
                <Font size="13.0" />
            </font>
        </Label>
        <TextField fx:id="nameTextField" layoutX="15.0" layoutY="35.0" prefHeight="25.0" prefWidth="400.0" />
        <TextField fx:id="pathTextField" layoutX="15.0" layoutY="105.0" prefHeight="25.0" prefWidth="400.0" />
    </children>
</AnchorPane>

Ogólny schemat programu:

Jeśli w  mainWindow.fxml (controller = MainController) zostanie wybrany file --> new --> E-mail to zadziała metoda openCreateEmail() która otworzy createEmailWindow.fxml (controller = MainController) gdzie po kliknięciu w przycisk finish zadziała metoda  finishButtonClicked() która powinna załadować emailTab.fxml czyli dodać nowy Tab do tabPane <-- to jest ID TabPane z mainWindow.fxml.

Trochę namieszałem ale mam nadzieję, że zrozumiecie na czym polega problem. Z góry dzięki za pomoc.

0

Zasadniczo - błąd w designie.

W JavieFX jedynym słusznym podejściem które znam jest osobny kontroler dla każdego pliku fxml (czyli dla każdej sceny).
createEmailWindow.fxml - nie ma swojego kontrolera, używa MainController, w momencie kiedy robisz

loader.setLocation(this.getClass().getResource("/res/mainWindow/createEmailWindow/createEmailWindow.fxml"));

tworzona jest nowa instancja MainController, referencję do niej możesz uzyskać poprzez loader.getController(). Ta instancja ma wstrzyknięte referencję jedynie do tych pól, które udało się znaleźć w pliku fxml, czyli w tym przypadku 3 buttony i 2 textfieldy, tabPane jest nullem, więc zgaduję że w tej linijce

tabPane.getTabs().add(tab);

leci NPE.

Rozwiązanie - osobny kontroler dla createEmailWindow.fxml, jeżeli potrzebujesz ustawić w nim jaieś zmienne to pobierasz referencję do instancji poprzez loader.getController() i ustawiasz co trzeba.

1 użytkowników online, w tym zalogowanych: 0, gości: 1