@FXML Annotation无法正常工作

时间:2018-03-09 11:54:49

标签: java javafx fxml fxmlloader

我目前正在使用JavaFX开展一个“小型”项目。我使用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设置为超链接,但它不起作用,因为我视图中的getter返回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为空,也不只是超链接。

我的错误在哪里?

2 个答案:

答案 0 :(得分:2)

问题是您使用new TestautomatView()手动创建控制器。它必须由FXMLLoader创建才能使注释生效。您还必须将fx:controller中的Sample.fxml属性设置为您的控制器(TestautomatView)完全限定的类名。

示例代码:

FXMLLoader fl = new FXMLLoader(new URL(TestautomatView.class.getResource("Sample.fxml").toExternalForm()));
root = fl.load();
TestautomatView controller = fl.getController();

PS:您应该将TestautomatView重命名为TestautomatController。 FXML文件是您的“视图”。

答案 1 :(得分:1)

正如另一个答案所指出的,问题是您手动创建了TestautomatView&#34;的实例&#34;。 FXMLLoader的默认行为是创建FXML文件中指定的控制器类的实例,并将该实例用作控制器。因此,您有两个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...

}

由于您是直接设置控制器,因此您需要fx:controller文件中删除Sample.fxml属性才能生效。

您可能也对this pattern感兴趣,这与您在此处尝试的内容非常相似(尽管不完全相同)。