簡體   English   中英

使用Scene Builder 8.0在JavaFX中使用setCenter()方法獲取空指針異常

[英]Getting Null Pointer Exception with setCenter() method in JavaFX with Scene Builder 8.0

我創建了一個小程序來重現我在實際項目中遇到的錯誤。 我有一個名為MainWindow.java的控制器類,它負責兩個.fxml文件: MainWindow.fxmlAnchorTest.fxml

控制器類的代碼:

package projecterror.controller;

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Screen;
import javafx.stage.Stage;

public class MainWindow extends Application {

    private Stage primaryStage;
    private BorderPane mainWindow;

    @FXML
    Menu menuFile, menuAnalysis;
    @FXML
    MenuItem menuNew;


    @FXML
    private void initialize() {
        menuNew.setOnAction((event) -> {
            try {
                FXMLLoader loader = new FXMLLoader();
                loader.setLocation(getClass().getResource("../view/AnchorTest.fxml"));
                AnchorPane anchorTest = (AnchorPane) loader.load();
                mainWindow.setCenter(anchorTest);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        this.primaryStage = primaryStage;
        this.primaryStage.setTitle("Test Project");

        initMainWindow();

    }

    public void initMainWindow() {
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(getClass().getResource("../view/MainWindow.fxml"));
            mainWindow = (BorderPane) loader.load();

            Scene scene = new Scene(mainWindow);
            primaryStage.setScene(scene);

            //Fullscreen
            Screen screen = Screen.getPrimary();
            Rectangle2D bounds = screen.getVisualBounds();
            primaryStage.setX(bounds.getMinX());
            primaryStage.setY(bounds.getMinY());
            primaryStage.setWidth(bounds.getWidth());
            primaryStage.setHeight(bounds.getHeight());

            primaryStage.setResizable(false);
            primaryStage.show();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

MainWindow.fxmlBorderPanetop具有MenuBar

碼:

<?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.layout.BorderPane?>

<BorderPane style="-fx-background-color: #DCDCDC;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="projecterror.controller.MainWindow">
    <top>
      <MenuBar BorderPane.alignment="CENTER">
        <menus>
          <Menu fx:id="menuFile" mnemonicParsing="false" text="File">
            <items>
                  <Menu fx:id="menuAnalysis" mnemonicParsing="false" text="Analysis">
                    <items>
                      <MenuItem fx:id="menuNew" mnemonicParsing="false" text="New" />
                    </items>
                  </Menu>
            </items>
          </Menu>
        </menus>
      </MenuBar>
   </top>
</BorderPane>


AnchorTest.fxml是一個AnchorPane ,具有兩個子AnchorPane

碼:

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

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

<AnchorPane xmlns:fx="http://javafx.com/fxml/1">
    <children>
            <AnchorPane layoutX="6.0" layoutY="450.0" />
            <AnchorPane layoutX="6.0" layoutY="569.0" prefHeight="116.0" prefWidth="730.0">
                  <Button layoutX="6.0"   layoutY="26.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="102.0" text="Button 1" />
                  <Button layoutX="115.0" layoutY="26.0" mnemonicParsing="false" prefWidth="102.0" text="Button 2" />
                  <Button layoutX="226.0" layoutY="26.0" mnemonicParsing="false" prefWidth="102.0" text="Button 3" />
                  <Button layoutX="115.0" layoutY="75.0" mnemonicParsing="false" prefWidth="102.0" text="Button 4" />
                  <Button layoutX="383.0" layoutY="26.0" mnemonicParsing="false" prefWidth="102.0" text="Button 5" />
                  <Button layoutX="491.0" layoutY="26.0" mnemonicParsing="false" prefWidth="102.0" text="Button 6" />
                  <Button layoutX="600.0" layoutY="26.0" mnemonicParsing="false" prefWidth="102.0" text="Button 7" />
                  <Button layoutX="491.0" layoutY="75.0" mnemonicParsing="false" prefWidth="102.0" text="Button 8" />
                  <Button layoutX="600.0" layoutY="75.0" mnemonicParsing="false" prefWidth="102.0" text="Button 9" />
                  <TextField alignment="TOP_CENTER" layoutX="341.0" layoutY="26.0" prefHeight="25.0" prefWidth="28.0" text="10" />
            </AnchorPane>
         </children>
</AnchorPane>


MainWindow.fxml ,單擊菜單File > Analysis > New ,應該將AnchorTest.fxml內容放入MainWindow.fxml中心。 但是,我得到以下堆棧跟蹤錯誤:

 Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
        at projecterror.controller.MainWindow.lambda$0(MainWindow.java:35)
        at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
        at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
        at javafx.event.Event.fireEvent(Event.java:198)
        at javafx.scene.control.MenuItem.fire(MenuItem.java:462)
        at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1405)
        at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$343(ContextMenuContent.java:1358)
        at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
        at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
        at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
        at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
        at javafx.event.Event.fireEvent(Event.java:198)
        at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
        at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
        at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
        at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:380)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:294)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:416)
        at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:415)
        at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
        at com.sun.glass.ui.View.notifyMouse(View.java:937)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
        at java.lang.Thread.run(Thread.java:745)

標記NPE的行是:

mainWindow.setCenter(anchorTest);

我已經閱讀了與此類似的其他問題,但大多數問題都與fxml文件的路徑有關。 of path for other views and I don't have problem so far. 我堅信這不是問題,因為在我的實際項目中,我對其他視圖使用相同的路徑,到目前為止,我還沒有遇到任何問題。

如果有人要運行該程序,我已經在這里上傳了該項目。

項目結構如下:

項目結構

在此先感謝您,任何幫助將不勝感激!

當您啟動JavaFX應用程序時,將創建您的應用程序類的實例,並且(在其他情況下)將在FX Application線程上的該Application實例上調用start()方法。

加載FXML文件時,如果FXML文件指定了控制器類, @FXML創建該控制器類的實例,將@FXML字段注入該實例中,並調用initialize()方法。 所有這些都在調用FXMLLoader.load()過程中發生。

因此,在您的代碼中,您最終得到MainWindow兩個不同實例。 在一個實例上調用start()方法,該實例將初始化mainWindow字段,在另一個實例上調用initialize()方法。 由於mainWindow從未在第二個實例中初始化,因此當您嘗試在initialize()方法中對其進行取消引用時,會出現空指針異常。

將控制器類與Application類分開。 Application類除了管理整個應用程序的生命周期外別無所求(通常,它應實現啟動應用程序所需的代碼):

package projecterror.controller;

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Screen;
import javafx.stage.Stage;

public class MainWindow extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("Test Project");

        initMainWindow(primaryStage);

    }

    public void initMainWindow(Stage primaryStage) {
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(getClass().getResource("../view/MainWindow.fxml"));
            BorderPane mainWindow = loader.load();

            Scene scene = new Scene(mainWindow);
            primaryStage.setScene(scene);

            //Fullscreen
            Screen screen = Screen.getPrimary();
            Rectangle2D bounds = screen.getVisualBounds();
            primaryStage.setX(bounds.getMinX());
            primaryStage.setY(bounds.getMinY());
            primaryStage.setWidth(bounds.getWidth());
            primaryStage.setHeight(bounds.getHeight());

            primaryStage.setResizable(false);
            primaryStage.show();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
package projecterror.controller;

import java.io.IOException;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;

public class MainWindowController {

    @FXML
    private BorderPane mainWindow;

    @FXML
    Menu menuFile, menuAnalysis;
    @FXML
    MenuItem menuNew;


    @FXML
    private void initialize() {
        menuNew.setOnAction((event) -> {
            try {
                FXMLLoader loader = new FXMLLoader();
                loader.setLocation(getClass().getResource("../view/AnchorTest.fxml"));
                AnchorPane anchorTest = (AnchorPane) loader.load();
                mainWindow.setCenter(anchorTest);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }



}

為了使控制器訪問BorderPane ,您需要從FXML注入它(請注意上面的控制器代碼中的注釋)。 fx:id添加到FXML文件中的元素:

<BorderPane style="-fx-background-color: #DCDCDC;" fx:id="mainWindow"
    xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" 
    fx:controller="projecterror.controller.MainWindowController">

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM