@FXML 注释无法正常工作
@FXML Annotation not working correctly
我目前正在使用 JavaFX 开发一个 'small' 项目。我使用 SceneBuilder 创建了我的 GUI 的第一个草图。它仍然需要一些调整和样式,但我想看看它到目前为止是否有效。
我在 GUI 上有 2 个超链接,如果用户单击其中之一,默认的系统浏览器应该打开特定的 URL。
到目前为止我得到了这个:
Main.java:
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws MalformedURLException, IOException {
DataBean dataBean= new DataBean(primaryStage);
Controller controller = new Controller(dataBean);
controller.show();
}
public static void main(String[] args) {
launch(args);
}
}
DataBean.java:
public class DataBean {
private Stage primaryStage;
public DataBean(Stage stage) {
primaryStage = stage;
}
public Stage getPrimaryStage() {
return primaryStage;
}
}
TestautomatView.java:
public class TestautomatView implements Initializable {
@FXML
private ComboBox<String> environmentCombo;
@FXML
private Hyperlink crhl;
@FXML
private Hyperlink help;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
private Scene scene;
private BorderPane root;
public TestautomatView() throws MalformedURLException, IOException {
root = FXMLLoader.load(new URL(TestautomatView.class.getResource("Sample.fxml").toExternalForm()));
scene = new Scene(root);
}
public void show(Stage stage) {
stage.setTitle("CrossReport Testautomat");
stage.setScene(scene);
stage.show();
}
public ComboBox<String> getEnvironmentCombo() {
return environmentCombo;
}
public Hyperlink getCrhl() {
return crhl;
}
public Hyperlink getHelp() {
return help;
}
public Scene getScene() {
return scene;
}
}
在我的控制器中,我想将 ActionHandler 设置为超链接,但它不起作用,因为我认为 getters return null。
public class Controller {
private DataBean dataBean;
private TestautomatView view;
public Controller(DataBean databean) throws MalformedURLException, IOException {
this.dataBean = databean;
this.view = new TestautomatView();
setActionHandlers();
}
public void show() throws MalformedURLException, IOException {
view.show(dataBean.getPrimaryStage());
}
private void setActionHandlers() {
// setHyperlink(view.getCrhl(), "www.example.com");
// setHyperlink(view.getHelp(), "www.example2.com");
}
private void setHyperlink(Hyperlink hl, String uri) {
hl.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
//TODO - Open Default Browser
}
});
}
}
当我启动我的应用程序时,我可以看到 GUI,但是当我想添加 ActionHandlers 时,我得到一个 NullPointerException。
在“Sample.fxml”文件中,超链接是 HBox 的子项
<Hyperlink fx:id="crhl" text="Report" />
<Hyperlink fx:id="help" text="Help" />
但不仅仅是超链接,当我在调试器中检查我的应用程序时,ComboBox 也为 null。
我的错误在哪里?
问题是您正在使用 new TestautomatView()
手动创建控制器。它必须由 FXMLLoader 创建才能使注释起作用。您还必须将 Sample.fxml
中的 fx:controller
属性设置为您的控制器 (TestautomatView
) 完全限定的 class 名称。
示例代码:
FXMLLoader fl = new FXMLLoader(new URL(TestautomatView.class.getResource("Sample.fxml").toExternalForm()));
root = fl.load();
TestautomatView controller = fl.getController();
PS:您应该将 TestautomatView
重命名为 TestautomatController
。 FXML 文件是您的 "view".
正如另一个答案所指出的,问题是您创建了 TestautomatView
"by hand" 的实例。 FXMLLoader
的默认行为是创建 FXML 文件中指定的控制器 class 的实例,并将该实例用作控制器。因此,您有两个 TestautomatView
的实例:一个是您创建的(并有一个引用),另一个是由 FXMLLoader
创建的。这是第二个初始化了 @FXML
注释字段的。
您可以通过创建 FXMLLoader
实例并直接在其上设置控制器来更改此默认行为。例如。考虑做:
public class TestautomatView implements Initializable {
@FXML
private ComboBox<String> environmentCombo;
@FXML
private Hyperlink crhl;
@FXML
private Hyperlink help;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
private Scene scene;
private BorderPane root;
public TestautomatView() throws MalformedURLException, IOException {
FXMLLoader loader = new FXMLLoader(TestautomatView.class.getResource("Sample.fxml"));
loader.setController(this);
root = loader.load();
scene = new Scene(root);
}
// etc...
}
由于您是直接设置控制器,因此您需要从Sample.fxml
文件中删除fx:controller
属性才能正常工作。
您可能也对 this pattern 感兴趣,它与您在这里尝试做的非常相似(尽管不完全相同)。
我目前正在使用 JavaFX 开发一个 'small' 项目。我使用 SceneBuilder 创建了我的 GUI 的第一个草图。它仍然需要一些调整和样式,但我想看看它到目前为止是否有效。
我在 GUI 上有 2 个超链接,如果用户单击其中之一,默认的系统浏览器应该打开特定的 URL。
到目前为止我得到了这个:
Main.java:
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws MalformedURLException, IOException {
DataBean dataBean= new DataBean(primaryStage);
Controller controller = new Controller(dataBean);
controller.show();
}
public static void main(String[] args) {
launch(args);
}
}
DataBean.java:
public class DataBean {
private Stage primaryStage;
public DataBean(Stage stage) {
primaryStage = stage;
}
public Stage getPrimaryStage() {
return primaryStage;
}
}
TestautomatView.java:
public class TestautomatView implements Initializable {
@FXML
private ComboBox<String> environmentCombo;
@FXML
private Hyperlink crhl;
@FXML
private Hyperlink help;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
private Scene scene;
private BorderPane root;
public TestautomatView() throws MalformedURLException, IOException {
root = FXMLLoader.load(new URL(TestautomatView.class.getResource("Sample.fxml").toExternalForm()));
scene = new Scene(root);
}
public void show(Stage stage) {
stage.setTitle("CrossReport Testautomat");
stage.setScene(scene);
stage.show();
}
public ComboBox<String> getEnvironmentCombo() {
return environmentCombo;
}
public Hyperlink getCrhl() {
return crhl;
}
public Hyperlink getHelp() {
return help;
}
public Scene getScene() {
return scene;
}
}
在我的控制器中,我想将 ActionHandler 设置为超链接,但它不起作用,因为我认为 getters return null。
public class Controller {
private DataBean dataBean;
private TestautomatView view;
public Controller(DataBean databean) throws MalformedURLException, IOException {
this.dataBean = databean;
this.view = new TestautomatView();
setActionHandlers();
}
public void show() throws MalformedURLException, IOException {
view.show(dataBean.getPrimaryStage());
}
private void setActionHandlers() {
// setHyperlink(view.getCrhl(), "www.example.com");
// setHyperlink(view.getHelp(), "www.example2.com");
}
private void setHyperlink(Hyperlink hl, String uri) {
hl.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
//TODO - Open Default Browser
}
});
}
}
当我启动我的应用程序时,我可以看到 GUI,但是当我想添加 ActionHandlers 时,我得到一个 NullPointerException。
在“Sample.fxml”文件中,超链接是 HBox 的子项
<Hyperlink fx:id="crhl" text="Report" />
<Hyperlink fx:id="help" text="Help" />
但不仅仅是超链接,当我在调试器中检查我的应用程序时,ComboBox 也为 null。
我的错误在哪里?
问题是您正在使用 new TestautomatView()
手动创建控制器。它必须由 FXMLLoader 创建才能使注释起作用。您还必须将 Sample.fxml
中的 fx:controller
属性设置为您的控制器 (TestautomatView
) 完全限定的 class 名称。
示例代码:
FXMLLoader fl = new FXMLLoader(new URL(TestautomatView.class.getResource("Sample.fxml").toExternalForm()));
root = fl.load();
TestautomatView controller = fl.getController();
PS:您应该将 TestautomatView
重命名为 TestautomatController
。 FXML 文件是您的 "view".
正如另一个答案所指出的,问题是您创建了 TestautomatView
"by hand" 的实例。 FXMLLoader
的默认行为是创建 FXML 文件中指定的控制器 class 的实例,并将该实例用作控制器。因此,您有两个 TestautomatView
的实例:一个是您创建的(并有一个引用),另一个是由 FXMLLoader
创建的。这是第二个初始化了 @FXML
注释字段的。
您可以通过创建 FXMLLoader
实例并直接在其上设置控制器来更改此默认行为。例如。考虑做:
public class TestautomatView implements Initializable {
@FXML
private ComboBox<String> environmentCombo;
@FXML
private Hyperlink crhl;
@FXML
private Hyperlink help;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
private Scene scene;
private BorderPane root;
public TestautomatView() throws MalformedURLException, IOException {
FXMLLoader loader = new FXMLLoader(TestautomatView.class.getResource("Sample.fxml"));
loader.setController(this);
root = loader.load();
scene = new Scene(root);
}
// etc...
}
由于您是直接设置控制器,因此您需要从Sample.fxml
文件中删除fx:controller
属性才能正常工作。
您可能也对 this pattern 感兴趣,它与您在这里尝试做的非常相似(尽管不完全相同)。