togglegroup - Problemas de compatibilidad con javafx 8-Campos estáticos de FXML
togglegroup javafx fxml (1)
Parece que estás intentando inyectar un TextField
en un campo estático. Algo como
@FXML
private static TextField myTextField ;
Esto aparentemente funcionó en JavaFX 2.2. No funciona en JavaFX 8. Dado que ninguna documentación oficial alguna vez admitió este uso, en realidad no viola la compatibilidad con versiones anteriores, aunque para ser justos, la documentación sobre exactamente lo que hace FXMLLoader
es bastante lamentable.
¿Por qué querrías hacer esto sin embargo? Es claramente una idea realmente terrible. Supongamos que decide reutilizar su archivo FXML dos veces en la misma aplicación: el segundo uso sobrescribirá el valor para el campo estático y se producirán todo tipo de caos. En pocas palabras, si intentas tener campos estáticos inyectados en tu controlador, de todos modos estás haciendo las cosas mal.
Actualización : respuesta a la pregunta en comentarios
En particular, no use campos estáticos solo para permitir que sean accesibles desde fuera de la clase. Un campo estático tiene un valor único que pertenece a la clase, en lugar de un valor para cada instancia de la clase, y la decisión de hacer que los campos sean estáticos solo debe hacerse si tiene sentido. Para permitir el acceso a los datos de la instancia, solo debe tener una referencia a la instancia. El FXMLLoader
tiene un método getController()
que le permite recuperar una referencia al controlador.
Un punto relacionado: tampoco es una buena idea exponer los controles de UI del controlador. En su lugar, debe exponer los datos. Por ejemplo, en lugar de definir un método getTextField()
en el controlador, en su lugar defina un método textProperty()
que devuelva StringProperty
representando el contenido del TextField
. La razón de esto es que cuando su jefe llega a la oficina y le dice que quiere que el TextField
sea reemplazado por un TextArea
, o un ComboBox<String>
, o algún otro control, entonces será mucho más difícil si las clases afuera del controlador están usando su TextField
. Es mucho menos probable que cambie la estructura de los datos representados por su controlador que la implementación de cómo se presentan esos datos al usuario.
Para algunos ejemplos
- Pasar los parámetros JavaFX FXML
- Gestión de datos JavaFX
- Acceda a campos de otro Controlador en 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
He diseñado una aplicación javafx que funciona bien en jdk 7. Cuando intento ejecutarla en java 8 obtengo las siguientes excepciones:
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)
Descubrí que la razón para esto está en el método de inicialización de la clase de controlador. No puedo usar los métodos incorporados en ningún componente estático. (Por ejemplo: staticMyTextField.setText () está causando el problema en java 8 pero no en java 7). No puedo encontrar nada documentado al respecto en las guías de javafx. ¿Puede alguien proporcionar algunas ideas sobre por qué esto está causando un problema en Java 8? Y también comparta documentos relacionados con esto, si corresponde.