2017-08-28 5 views
0

私はルートとしてStackPaneを持っており、メインアプリケーションのStart()メソッドでBorderPaneレイアウトをロードしています。 BorderPaneレイアウトには2つのボタンがあります:1つはfxmlファイル(Menu.fxml)を追加し、もう1つはこのファイルを削除します。 Menu.fxmlがロードされたら、Menu.fxmlのボタンをクリックすると、以前にロードされたBorderPaneレイアウトの中央にfxmlファイル(One.fxml)がロードされます。 しかし、この段階では、NULLポインタ例外が発生します。私が間違っているところを指摘してください。 ありがとうございます。以下はJavaFX8ヌルポインタコントローラからFXMLファイルをロードする際の例外

私のコードです:


public class Main extends Application { 

    private static StackPane rootStack; 
    private static BorderPane rootBorder; 

    @Override 
    public void start(Stage stage) throws Exception { 
     rootStack = FXMLLoader.load(getClass().getResource("Base.fxml")); 
     rootBorder = FXMLLoader.load(getClass().getResource("Border.fxml")); 
     rootStack.getChildren().addAll(rootBorder); 

     Scene scene = new Scene(rootStack); 
     stage.setScene(scene); 
     stage.show(); 
    } // start 

    public static StackPane getRootStack() { 
     return rootStack; 
    } // end of method getRootStack 

    public static BorderPane getRootBorder() { 
     return rootBorder; 
    } // end of method getRootBorder 

    public static void main(String[] args) { 
     launch(args); 
    } // launch 

} // Main 

public class BorderController { 

    private StackPane rootStack = Main.getRootStack(); 
    VBox menu; 

    public void initialize() throws IOException { 
     menu = FXMLLoader.load(getClass().getResource("Menu.fxml")); 
    } // initialize  

    @FXML 
    private void addMenuPane(ActionEvent event) throws IOException { 
     rootStack.getChildren().add(menu); 
    } // addMenuPane 

    @FXML 
    private void removeNode(ActionEvent event) { 
     rootStack.getChildren().remove(menu); 
    } // removeNode 

} // BorderController 

public class MenuController { 

    private BorderPane rootBorder = Main.getRootBorder(); 

    @FXML 
    private JFXButton oneButton; 

    public void initialize() { 
     oneButton.addEventHandler(MouseEvent.MOUSE_CLICKED, (event) -> { 
      try { 
       rootBorder.setCenter(FXMLLoader.load(getClass().getResource("One.fxml"))); 
      } catch (IOException ex) { 
       Logger.getLogger(MenuController.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     }); 

    } // initialize  

} // MenuController 

スタックトレース:

Executing C:\Users\User\Documents\NetBeansProjects\Stack\dist\run2093523570\Stack.jar using platform C:\Program Files\Java\jdk1.8.0_121\jre/bin/java 
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException 
    at stack.MenuController.lambda$initialize$0(MenuController.java:22) 
    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.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$ClickGenerator.postProcess(Scene.java:3470) 
    at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3398) 
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3766) 
    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:381) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:417) 
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416) 
    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) 
Deleting directory C:\Users\User\Documents\NetBeansProjects\Stack\dist\run2093523570 
+0

完全なスタックトレースを質問に投稿してください。 –

+0

'rootBorder'がnullのようです。それを確認できますか? –

+0

あなたのコードを読むことができます。 'MenuController'のイベントハンドラで' rootBorder'がnullであることを確認するようお願いしています。デバッグ行をイベントハンドラに入れるだけです。 'if(rootBorder == null)System.out.println(" Warning:rootBorder is null ");'メッセージが表示されているかどうかを確認します。または、イベントハンドラの先頭にブレークポイントを置き、デバッガでブレークポイントを実行します。 –

答えて

2

FXMLファイルのルート要素はfx:controller属性を持っている場合は、FXMLファイルをロードすると、その属性で指定されたクラスは、任意の@FXML -annotatedフィールドが注入され、インスタンス化され、そしてinitialize()メソッドが呼び出されましたコントローラークラスインスタンス(存在する場合)このすべてはload()メソッドの一部としてFXMLLoaderの一部として発生します。あなたはApplication.start()メソッド内のコードの行を考慮した場合

rootBorder = FXMLLoader.load(getClass().getResource("Border.fxml")); 

この、Border.fxmlをロードするコントローラを作成します、など、そのinitialize()メソッドを呼び出し、かつ完全であることすべては、それが割り当てられます場合にのみ、結果はrootBorderになります。呼び出されるBorderControllerinitialize()メソッドは、Menu.fxmlをロードします。次にコントローラがMenu.fxmlにインスタンス化されます。これはMenuControllerです。 MenuControllerための初期化コードは、この時点で、Border.fxmlを読み込んでload()方法が依然としてMainにおける静的rootBorderフィールドがまだ割り当てられていないので、終了し、そうMain.getRootBorder()戻っていないことをnull

private BorderPane rootBorder = Main.getRootBorder(); 

注を含みます。あなたは

rootBorder.setCenter(...); 

をしようとするとき

その結果、後でrootBorderは値nullを割り当てられているので、あなたは、nullポインタ例外を取得します。間に合わせの修正プログラムはちょうどあなたがそれを必要とする瞬間に、ボーダー・ペインを取得することです

public class MenuController { 

    @FXML 
    private JFXButton oneButton; 

    public void initialize() { 
     oneButton.addEventHandler(MouseEvent.MOUSE_CLICKED, (event) -> { 
      try { 
       Main.getRootBorder().setCenter(FXMLLoader.load(getClass().getResource("One.fxml"))); 
      } catch (IOException ex) { 
       Logger.getLogger(MenuController.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     }); 

    } // initialize  

} // MenuController 

Applicationサブクラスの静的フィールドを使用するこのアプローチは、しかし、本当に悪いデザインです。すべての種類の不必要な結合(あなたのMenuControllerは本当にその特定のMainクラスの存在に依存していますか?)を公開し、公開すべきではないすべての種類のUI要素を公開します。 UIコードベース全体を変更する必要があります)。このようにする必要がないように、おそらくこれを再構成するべきです。

+0

この問題の原因を説明する時間をとってくれてありがとうJames_Dに感謝します。心から感謝する。メインクラスで静的フィールドを使用していた唯一の理由は、他のコントローラクラスのBorderPaneレイアウトにアクセスして、ユーザーが選択したメニューに従ってロードする必要があったためです。上記の結果につながったインターネット上のチュートリアルを検索する以外に、私は正しい方向に私を導くことができる他のリソースがありません。私はJavaFXでの作業を本当に楽しんでおり、この特定のプロジェクトを再構築する正しい方法を学びたいと思っています。 – snow

+0

このシナリオの良い設計例はありますか?それで私はそれから学ぶことができますか?私はJavaFXを学ぶためにDietel Java How to Programテキストブックを使用してきましたが、材料は限られていて、基本的な概念だけをカバーしています。 JavaFXの詳細を学ぶための参考資料はありますか?私は真に私の知識を学び、向上させたいと思っています。ご協力いただきありがとうございます。 – snow

+0

@snow github.com/acaicedo/Screen-Frameworkをご覧ください。後で時間があるなら、私は答えを詳しく説明します。 –

関連する問題