【问题标题】:javafx fxml is null outside initialize()javafx fxml 在 initialize() 之外为空
【发布时间】:2013-07-13 22:01:04
【问题描述】:

在这段代码中:

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);

}

}

我不明白为什么它在 initialise() 中有一个值,但一开始它是空的。调试时很明显,FXMLLOader 从 start() 内部调用了 initiialize()

我打算发布 fxml,但它似乎没有像预览中显示的那样工作。无论如何,它是一个真正的基本文件,一个 BordePane 和一个 ToolBar。

有什么线索吗?

【问题讨论】:

    标签: javafx fxml


    【解决方案1】:

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

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

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

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

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

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

    总之,要解决这个问题:

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

    如果您的应用程序确实需要引用控制器,那么您可以在 FXML 加载器上使用 getController 方法,并在您的控制器类中提供公共方法来检索所需的元素(如菜单栏)。有关此方法的更多示例,请参阅我对 Passing Parameters 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 ";     
      }
    }
    

    【讨论】:

    • 另一个解决方法是在加载之前创建一个 FXMLLoader 实例并在其上调用 setController。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-04
    • 1970-01-01
    • 2016-11-07
    • 2013-06-25
    相关资源
    最近更新 更多