当前位置: 首页 > 知识库问答 >
问题:

javafx fxml在initialize()之外为空

梁丘远航
2023-03-14

在此代码中:

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()中有一个值,但在start中却是空的。调试时,很明显,initialize()是由FXMLLOader从start()内部调用的

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

有线索吗?

共有1个答案

包和泰
2023-03-14

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

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

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

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

因此,在您的代码中,发生的情况是:

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

总之,要解决此问题:

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

如果应用程序确实需要引用控制器,那么可以在FXML加载器上使用getController方法,并在controller类中提供公共方法来检索所需元素(如菜单栏)。有关此方法的更多示例,请参阅我对传递参数的回答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 ";     
  }
}
 类似资料:
  • 描述 (Description) 它使用new关键字实例化视图,并在首次创建视图时调用。 语法 (Syntax) new View(options) 参数 (Parameters) options - 这些是可选参数,可以是model,collection,el,id,className,tagName,attributes和events。 例子 (Example) <!DOCTYPE html

  • 描述 (Description) 它为路由器实例化创建了一个新的构造函数。 语法 (Syntax) new Router(options) 参数 (Parameters) options - 将这些传递给初始化函数。 例子 (Example) <!DOCTYPE html> <html> <head> <title>Router Example</title> <s

  • 描述 (Description) 创建模型实例时,通过在创建集合时定义initialize函数来调用它。 语法 (Syntax) new Backbone.Collection(models, options) 参数 (Parameters) models - 它指定了最初的模型数组。 options - 这些是由传递的模型对象直接附加到集合的集合类型。 例子 (Example) <!DOCTY

  • 描述 (Description) 创建模型实例时,将调用类的构造函数,并通过定义initialize函数来调用它。 语法 (Syntax) new Model(attributes, options) 参数 (Parameters) attributes - 属性在创建模型的实例时定义模型的属性。 options - 这些是id,name等选项,在创建模型时与属性一起使用。 例子 (Exampl

  • 核心问题:如果绑定属性在声明绑定属性的方法之外更新,则对象无效侦听器不会触发。 以JavaFX UI控制器类中声明的方法为例: 如您所见,我声明了一个,它依赖于TextField的text属性,称为,并声明了一个,它在无效时请求计算。 如果我在initialize方法中编辑值,则会触发和更改侦听器,而如果我从UI编辑值,则只会触发更改侦听器。 有人能解释一下为什么会这样吗?

  • 问题内容: 我想做一些事情,在控制器的initialize()方法完成之后,但要在场景显示之前。是否要在场景显示之前调用任何方法?我想在该方法中放入一些代码。 我无法将代码放入initialize()方法中,因为它将在fxml文件加载时(当我尚未获取控制器时)被调用。那么,我该怎么办? 非常感谢 ! 问题答案: 我发现的一种解决方案 此事件在显示之前在窗口上发生。doc连结