1

In this code:

public class ESM extends Application {

private Stage primaryStage;

@FXML 
private ToolBar mainToolBar;


@Override
public void start(final Stage stage) throws Exception {
    try{
        this.primaryStage = stage;
        Parent root = FXMLLoader.load(getClass().getResource("/nz/co/great_ape/esm3/main_window.fxml"));

        Scene scene = new Scene(root, 800, 700);            
        //  Setup main stage to be full screen, no min or max buttons.
        //  TODO:  How will this handle multiple screens?  Apparently not well :-(
        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.initStyle(StageStyle.UNDECORATED); 
        primaryStage.setTitle("ESM three");
        primaryStage.setScene(scene);
        primaryStage.show();
        System.out.println("This will fail because mainToolBar is null.  Why?");
        assert mainToolBar != null : "fx:id=\"mainToolBar\" was null check your FXML ";
    } catch (Exception ex) {
        Logger.getLogger(ESM.class.getName()).log(Level.SEVERE, null, ex);
    }           
}



/**
 * Use initialize() to setup widgets from scenebuilder files, it is
 * called by FXMLLoader.
 */
@FXML
public void initialize(){
    System.out.println("initialize() But when here all is good and mainToolBar is a ToolBar.");
    assert mainToolBar != null : "fx:id=\"mainToolBar\" was null check your FXML ";     
}

/**
 * The main() method is ignored in correctly deployed JavaFX application.
 * main() serves only as fallback in case the application can not be
 * launched through deployment artifacts, e.g., in IDEs with limited FX
 * support. 
 *
 * @param args The command line arguments.
 */
public static void main(String[] args) {
    launch(args);

}

}

I cant see why it's got a value in the initialise() but in the start it's null. When debuging it's clear that initiialize() is called by FXMLLOader from inside start()

I was going to post the fxml but it does not seem to work as nothig shows in the preview. Any way, it's a real basic file, a BordePane and a ToolBar.

Any clues?

4

1 回答 1

7

始终为您的 FXML 控制器创建一个新类,不要尝试将应用程序类重用为控制器类。

应用程序实例由 JavaFX 应用程序启动器创建。

控制器实例由 JavaFX FXML 加载器创建。

您没有提供您使用的 FXML,但我猜测它的 Controller 类错误地设置为您的应用程序类。

所以在你的代码中,会发生什么:

  1. 当您运行程序时(通过启动方法),将创建应用程序的一个实例。
  2. 在您的应用程序启动方法中,您调用 FXMLLoader,它实例化一个新控制器(在您的情况下是应用程序类的新实例)。
  3. FXMLLoader 将@FXML 标记的成员注入的应用程序对象并调用对象的初始化。
  4. 但是您的原始应用程序对象对新应用程序对象一无所知,因此其中没有设置菜单栏。

总之,要解决这个问题:

  1. 创建一个 FXMLLoader 可以实例化的新控制器类。
  2. 更改您的 fxml 以引用新的控制器类。

如果您的应用程序确实需要引用控制器,那么您可以在 FXML 加载器上使用getController方法,并在您的控制器类中提供公共方法来检索所需的元素(如菜单栏)。有关此方法的更多示例,请参阅我对传递参数 JavaFX FXML的回答。

import javafx.scene.control.ToolBar;
import javafx.fxml.FXML;

public class ESMController {
  @FXML 
  private ToolBar mainToolBar;
  public  ToolBar getMainToolBar() { return mainToolBar; }

  @FXML
  public void initialize(){
    assert mainToolBar != null : "fx:id=\"mainToolBar\" was null check your FXML ";     
  }
}
于 2013-07-14T05:21:55.260 回答