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

查看:36
本文介绍了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)

我发现原因是在控制器类的初始化方法中,我无法在任何静态组件中使用内置方法.(例如: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 注入的字段设为静态并没有多大意义.加载 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() 方法,该方法返回一个表示内容的 StringPropertyTextField 的.这样做的原因是,当您的老板来到办公室并告诉您他希望将 TextField 替换为 TextAreaComboBox 时. 或其他一些控件,那么如果控制器之外的类正在使用您的 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.

一些例子

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

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