无法在 JavaFX 项目中实例化 class 个字段
Can't instantiate class fields in JavaFX project
所以我试图从 Swing 转移到 JavaFX,我只是声明了 start()
和 launch()
方法,而不知道它们是如何工作的。但是下面的代码将 false 和 false 打印到控制台。然而,当我单击 GUI 中的按钮时,使用 Scene Builder
构建,执行 myMethod()
,这次它打印 true。为什么说 primaryStage
没有被实例化?
补充信息:
出于同样的原因,我也将此 class 作为我的控制器 - 它需要访问 Stage 引用。如果重要的话,我没有 post 的完整版 Main 实现了 Initializable
。
作为奖励问题 我想知道我是否需要 primaryStage
的字段来引用申请阶段,其中只有一个?,在 myMethod()
.
public class Main extends Application {
private Stage primaryStage;
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
try {
Scene scene = new Scene(FXMLLoader.load(getClass().getResource("Sample.fxml")),600,400);
primaryStage.setScene(scene);
} catch(Exception e) {
e.printStackTrace();
}
primaryStage.show();
//both lines below print false; As they should.
System.out.println(this.primaryStage == null);
myMethod();
}
public static void main(String[] args) {
launch(args);
}
public void myMethod() {
System.out.println(primaryStage == null);
}
}
编辑
将此 FXML 文档放在与上面相同的文件夹中 class 将让您 运行 Main 看到按钮确实打印 true。
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<HBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Main">
<children>
<Button mnemonicParsing="false" onAction="#myMethod" text="Button" />
</children>
</HBox>
这是因为 FXMLLoader
将创建 application.Main
class 的新实例,其中 start()
方法未被调用,因此 private Stage primaryStage
是空。
FXML的主class和controller还是分开比较好,必要的时候再过初级:
...
try
{
FXMLLoader loader = new FXMLLoader( getClass().getResource( "Sample.fxml" ) );
Scene scene = new Scene( loader.load(), 600, 400 );
( (MyController) loader.getController() ).setPrimaryStage(primaryStage);
primaryStage.setScene( scene );
}
catch ( Exception e )
{
e.printStackTrace();
}
...
其中 MyController
class 可以简单为:
public class MyController {
private Stage primaryStage;
public void setPrimaryStage(Stage primaryStage) {
this.primaryStage = primaryStage;
}
}
还可以实现Initializable interface. Refer to Introduction to FXML :: Controllers.
另请注意,您可以通过以下方式从构成该场景图(即显示的舞台)的任何节点获取场景及其舞台:
Scene scene = anynode.getScene();
Stage primaryStage = (Stage) anynode.getScene().getWindow();
当然,对于您创建的次要阶段,getWindow() 将 return 该阶段而不是主要阶段。
根本不需要跳过任何这些环圈就可以访问 window。您可以在任何节点上调用 getScene().getWindow()
以获取显示它的 window (当然您可以以通常的方式将任何节点注入您的控制器)。
不要使用 Application
subclass 作为控制器 class:你将有(至少)两个不同的实例(一个由 launch()
方法,因为它是 Application
subclass,并且由 FXMLLoader
创建,因为它是控制器 class)。不同的实例会初始化不同的字段。
创建控制器class,并向其中至少注入一个节点:
public class Controller {
@FXML
private Parent root ;
@FXML
private void myMethod() {
Window window = root.getScene().getStage();
// assuming you are running as a standalone application, the window
// will actually be a Stage instance.
window.hide(); // for example...
}
}
将其用作您的控制器class并将节点注入其中:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<HBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller" fx:id="root">
<children>
<Button mnemonicParsing="false" onAction="#myMethod" text="Button" />
</children>
</HBox>
所以我试图从 Swing 转移到 JavaFX,我只是声明了 start()
和 launch()
方法,而不知道它们是如何工作的。但是下面的代码将 false 和 false 打印到控制台。然而,当我单击 GUI 中的按钮时,使用 Scene Builder
构建,执行 myMethod()
,这次它打印 true。为什么说 primaryStage
没有被实例化?
补充信息:
出于同样的原因,我也将此 class 作为我的控制器 - 它需要访问 Stage 引用。如果重要的话,我没有 post 的完整版 Main 实现了 Initializable
。
作为奖励问题 我想知道我是否需要 primaryStage
的字段来引用申请阶段,其中只有一个?,在 myMethod()
.
public class Main extends Application {
private Stage primaryStage;
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
try {
Scene scene = new Scene(FXMLLoader.load(getClass().getResource("Sample.fxml")),600,400);
primaryStage.setScene(scene);
} catch(Exception e) {
e.printStackTrace();
}
primaryStage.show();
//both lines below print false; As they should.
System.out.println(this.primaryStage == null);
myMethod();
}
public static void main(String[] args) {
launch(args);
}
public void myMethod() {
System.out.println(primaryStage == null);
}
}
编辑
将此 FXML 文档放在与上面相同的文件夹中 class 将让您 运行 Main 看到按钮确实打印 true。
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<HBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Main">
<children>
<Button mnemonicParsing="false" onAction="#myMethod" text="Button" />
</children>
</HBox>
这是因为 FXMLLoader
将创建 application.Main
class 的新实例,其中 start()
方法未被调用,因此 private Stage primaryStage
是空。
FXML的主class和controller还是分开比较好,必要的时候再过初级:
...
try
{
FXMLLoader loader = new FXMLLoader( getClass().getResource( "Sample.fxml" ) );
Scene scene = new Scene( loader.load(), 600, 400 );
( (MyController) loader.getController() ).setPrimaryStage(primaryStage);
primaryStage.setScene( scene );
}
catch ( Exception e )
{
e.printStackTrace();
}
...
其中 MyController
class 可以简单为:
public class MyController {
private Stage primaryStage;
public void setPrimaryStage(Stage primaryStage) {
this.primaryStage = primaryStage;
}
}
还可以实现Initializable interface. Refer to Introduction to FXML :: Controllers.
另请注意,您可以通过以下方式从构成该场景图(即显示的舞台)的任何节点获取场景及其舞台:
Scene scene = anynode.getScene();
Stage primaryStage = (Stage) anynode.getScene().getWindow();
当然,对于您创建的次要阶段,getWindow() 将 return 该阶段而不是主要阶段。
根本不需要跳过任何这些环圈就可以访问 window。您可以在任何节点上调用 getScene().getWindow()
以获取显示它的 window (当然您可以以通常的方式将任何节点注入您的控制器)。
不要使用 Application
subclass 作为控制器 class:你将有(至少)两个不同的实例(一个由 launch()
方法,因为它是 Application
subclass,并且由 FXMLLoader
创建,因为它是控制器 class)。不同的实例会初始化不同的字段。
创建控制器class,并向其中至少注入一个节点:
public class Controller {
@FXML
private Parent root ;
@FXML
private void myMethod() {
Window window = root.getScene().getStage();
// assuming you are running as a standalone application, the window
// will actually be a Stage instance.
window.hide(); // for example...
}
}
将其用作您的控制器class并将节点注入其中:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<HBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller" fx:id="root">
<children>
<Button mnemonicParsing="false" onAction="#myMethod" text="Button" />
</children>
</HBox>