javafx 8兼容性问题 - FXML静态字段 [英] javafx 8 compatibility issues - FXML static fields

查看:312
本文介绍了javafx 8兼容性问题 - FXML静态字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设计了一个在jdk 7中运行良好的javafx应用程序。当我尝试在java 8中运行它时,我得到以下例外:

I have designed a javafx application which works fine in jdk 7. When I try to run it in java 8 I am getting the below exceptions:

javafx.fxml.LoadException: 
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2617)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2595)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3230)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3191)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3164)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3140)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3132)


Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Root cannot be null
    at javafx.scene.Scene.<init>(Scene.java:364)
    at javafx.scene.Scene.<init>(Scene.java:232)
        at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:204)
    at javafx.concurrent.EventHelper.fireEvent(EventHelper.java:219)
    at javafx.concurrent.Task.fireEvent(Task.java:1357)
    at javafx.concurrent.Task.setState(Task.java:720)
    at javafx.concurrent.Task$TaskCallable$2.run(Task.java:1438)
    at com.sun.javafx.application.PlatformImpl$6$1.run(PlatformImpl.java:301)
    at com.sun.javafx.application.PlatformImpl$6$1.run(PlatformImpl.java:298)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl$6.run(PlatformImpl.java:298)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.access$300(WinApplication.java:39)
    at com.sun.glass.ui.win.WinApplication$4$1.run(WinApplication.java:112)
    at java.lang.Thread.run(Thread.java:744)

我发现这个的原因是在控制器类的initialize方法中我无法使用内置方法在任何静态组件中。 (例如:staticMyTextField.setText()导致java 8中的问题,但不会导致java 7中的问题)。我无法在javafx指南中找到有关此内容的任何文档。有人可以提供一些关于为什么这会导致Java 8问题的想法吗?并且还分享与此相关的文档(如果有的话)。

I found out the reason for this is in the initialize method of the controller class I am not able to use the inbuilt methods in any static component. (For example: staticMyTextField.setText() is causing the problem in java 8 but not in java 7). I am not able to find out anything documented regarding this in the javafx guides. Can someone please provide some ideas on why this is causing an issue in Java 8? And also share documents related to this if any.

推荐答案

听起来你正在尝试注入 TextField 进入静态字段。类似

It sounds like you are trying to inject a TextField into a static field. Something like

@FXML
private static TextField myTextField ;

这显然适用于JavaFX 2.2。它在JavaFX 8中不起作用。因为没有官方文档曾经支持过这种用法,所以它并没有真正违反向后兼容性,尽管公平地说明了 FXMLLoader 的确切文档确实非常糟糕。

This apparently worked in JavaFX 2.2. It doesn't work in JavaFX 8. Since no official documentation ever supported this use, it's doesn't really violate backward compatibility, though in fairness the documentation on exactly what the FXMLLoader does is pretty woeful.

@FXML -injected fields static设置为没有多大意义。加载FXML文件时,它会为FXML文件中的每个元素创建新对象。一个新的控制器实例与每次调用 FXMLLoader.load(...)相关联,并且该控制器实例中的字段将注入相应的为FXML元素创建的对象。因此,注入的字段必须特定于控制器实例。如果你在控制器中有一个静态注入字段,并且你加载了相同的FXML文件两次并在UI中显示两次,那么你将无法引用这两组控件。

It doesn't really make much sense to make @FXML-injected fields static. When you load an FXML file, it creates new objects for each of the elements in the FXML file. A new controller instance is associated with each call to FXMLLoader.load(...) and the fields in that controller instance are injected with the corresponding objects created for the FXML elements. So the injected fields are necessarily specific to the controller instance. If you had a static injected fields in the controller, and you loaded the same FXML file twice and displayed it twice in the UI, then you would have no way of referencing both sets of controls.

更新:回复评论中的问题

特别是,不要仅使用静态字段来启用它们来自课外。静态字段具有属于该类的单个值,而不是该类的每个实例的值,并且只有在有意义的情况下才应该将字段设置为静态。换句话说, static 定义范围,而不是辅助功能。要允许访问实例数据,您只需要引用该实例。 FXMLLoader 有一个 getController()方法,允许您检索对控制器的引用。

In particular, don't use static fields just to enable them to be accessible from outside the class. A static field has a single value belonging to the class, instead of a value for each instance of the class, and the decision to make fields static should only be made if that makes sense. In other words, static defines scope, not accessibility. To allow access to instance data, you just have to have a reference to the instance. The FXMLLoader has a getController() method that allows you to retrieve a reference to the controller.

一个相关点:从控制器公开UI控件也不是一个好主意。您应该改为公开数据。例如,不是在控制器中定义 getTextField()方法,而是定义返回的 textProperty()方法 StringProperty 表示 TextField 的内容。这样做的原因是当你的老板来到办公室并告诉你他希望用 TextArea TextField 时c>,或者 ComboBox< String> ,或者其他一些控件,如果控制器外的类使用你的的TextField 。由控制器代表的数据结构比实现向用户呈现数据的方式更不可能发生变化。

A related point: it's also not a good idea to expose the UI controls from the controller. You should instead expose the data. For example, instead of defining a getTextField() method in the controller, instead define a textProperty() method that returns a StringProperty representing the contents of the TextField. The reason for this is that when your boss comes to the office and tells you he wants the TextField to be replaced by a TextArea, or a ComboBox<String>, or some other control, then it's going to be a lot harder if classes outside of the controller are using your TextField. The structure of the data represented by your controller is much less likely to change than the implementation of how that data is presented to the user.

对于某些示例

  • Passing Parameters JavaFX FXML
  • JavaFX Data Mangement
  • Access fields from another Controller in JavaFX
  • https://github.com/james-d/LeastCommonMultipleCalculator
  • https://github.com/james-d/Nested-Controller-Example
  • https://github.com/james-d/Dialog-FXML-Example
  • https://github.com/james-d/Shared-Data-Controller

这篇关于javafx 8兼容性问题 - FXML静态字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆