2017-12-28 49 views
0

実際のプロジェクトで発生しているエラーを再現するための小さなプログラムを作成しました。 2つの.fxmlファイルを担当するMainWindow.javaというコントローラクラスがあります:MainWindow.fxmlAnchorTest.fxmlです。コントローラクラスの

コード:シーンビルダー8.0を使用したJavaFXのsetCenter()メソッドによるヌルポインタ例外の取得

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.fxmltopMenuBarを持っBorderPaneです。

コード:

<?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子供2 AnchorPaneとして持っていAnchorPaneです。

コード:私はメニューFile > Analysis > Newをクリックした後MainWindow.fxml

<?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センターへAnchorTest.fxmlコンテンツを配置することになっています。 NPEにフラグを設定されて

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) 

行されています:私はこれに似ていますが、ほとんどは彼らの問題のすべてがに関してれた他の質問を読んでいる

mainWindow.setCenter(anchorTest); 

しかし、私は、次のスタックトレースのエラーを取得しますfxmlファイルのパス。実際のプロジェクトでは他のビューにも同様のタイプのを使用していますので、これは問題ではないと確信しています。

誰かがプログラムを実行したい場合に備えて、hereプロジェクトをアップロードしました。それは次のように

プロジェクト構造は次のとおりです。

Project structure

事前に感謝し、任意の助けをいただければ幸いです!

+0

このようにして「JavaFX Main」を構成したことはありません。 – Sedrick

+0

また、プロジェクトの構造を投稿する必要があります。 – Sedrick

+1

'mainWindow'はコントローラで初期化されていません。アプリケーションが起動されたとき( 'start()'が呼び出されるインスタンス)に作成される 'Application'インスタンスで初期化されます。ここでは、アプリケーションクラスをコントローラクラスとして使用しないでください。それはあまりにも混乱します(そして、 "Single Responsibility"のような基本的なOOP設計原則に違反します)。 –

答えて

2

JavaFXアプリケーションを起動すると、アプリケーションクラスのインスタンスが作成され、その他の場合には、start()メソッドがFXアプリケーションスレッドのApplicationインスタンスで呼び出されます。

FXMLファイルをロードするとき、FXMLファイルでコントローラクラスが指定されている場合、そのコントローラクラスのインスタンスが作成され、@FXML - 注釈付きフィールドがそのインスタンスに注入され、initialize()メソッドが呼び出されます。このすべては、FXMLLoader.load()への通話中に発生します。

したがって、コードでは、MainWindowの2つの異なるインスタンスになります。 mainWindowフィールドを初期化する1つのインスタンスでstart()メソッドが呼び出され、もう1つのインスタンスでinitialize()メソッドが呼び出されます。その2番目のインスタンスでmainWindowが初期化されていないので、initialize()メソッドで逆参照しようとすると、NULLポインタ例外が発生します。

コントローラークラスを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(); 
      } 
     }); 
    } 



} 

Applicationクラスは、全体(一般的に、それはアプリケーションを起動するために必要なコードを実装する必要があります)などのアプリケーションのライフサイクルを管理する以外に何もしないはずですBorderPaneにアクセスするには、FXMLから注入する必要があります(上のコントローラコードの注釈を参照してください)。 FXMLファイルの要素にfx:idを追加してください:

<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"> 
+0

完全性のために、私はMainWindowクラスの中で 'private stage primaryStage;'を忘れたと思います。それはあなたの説明のおかげで、完璧に動作します。 – leandrocoutom

+1

@leandrocoutom実際には、 'start()'と 'initMainWindow()'メソッドでのみ必要なので、私は省略しようとしましたが、私は変更を完了しませんでした。私に修正させて.... –

関連する問題