我目前正在使用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为空,也不只是超链接。
我的错误在哪里?
答案 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感兴趣,这与您在此处尝试的内容非常相似(尽管不完全相同)。