I have an FXML file defining a JavaFX user interface. Within the FXML file, I have the following:
...
<Checkbox fx:id="myCheckbox" ... />
<Spinner disable="${myCheckbox.selected}" ... />
...
When I try to load my FXML file with the following code, I get a javafx.fxml.LoadException
with the message
Cannot bind to untyped object.
final Class<?> controllerClass = ...;
final FXMLLoader fxmlLoader = new FXMLLoader();
final String fxmlPath = controllerClass.getSimpleName() + ".fxml";
try (final InputStream fxmlStream = controllerClass.getResourceAsStream(fxmlPath)) {
fxmlLoader.load(fxmlStream);
final Object controller = fxmlLoader.<Object>getController();
return controller
}
Does anyone know how to modify the FXML to disable my spinner when the checkbox is checked? I know how to go about this in code, but want to learn more about the FXML syntax. I should also add that when I remove the attempted property binding from the FXML, everything loads as expected. Thanks.
EDIT
Due to the comment from @Groostav saying that it must be something in the ...
portion of the code, I came up with a minimal, reproducible example. In my example, there are two files, which I will copy in their entirety here.
Main.java:
package test;
import java.io.InputStream;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(final String[] args) {
launch(args);
}
@Override
public void start(Stage window) throws Exception {
final FXMLLoader fxmlLoader = new FXMLLoader();
final String fxmlPath = "Example.fxml";
final Parent root;
try (final InputStream fxmlStream = getClass().getResourceAsStream(fxmlPath)) {
root = (Parent)fxmlLoader.load(fxmlStream);
}
final Scene scene = new Scene(root);
window.setScene(scene);
window.show();
}
}
Example.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Spinner?>
<?import javafx.scene.layout.HBox?>
<HBox xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1"
alignment="BASELINE_LEFT" spacing="15">
<children>
<CheckBox fx:id="myCheckbox" text="Disable?" mnemonicParsing="false" />
<Spinner disable="${myCheckbox.selected}" />
</children>
</HBox>
When I run the main method, I get the following output:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:745)
Caused by: javafx.fxml.LoadException: Cannot bind to untyped object.
unknown path:12
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2597)
at javafx.fxml.FXMLLoader.access$100(FXMLLoader.java:103)
at javafx.fxml.FXMLLoader$Element.processPropertyAttribute(FXMLLoader.java:299)
at javafx.fxml.FXMLLoader$Element.processInstancePropertyAttributes(FXMLLoader.java:235)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:749)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2425)
at test.Main.start(Main.java:22)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
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.lambda$null$148(WinApplication.java:191)
... 1 more
Exception running application test.Main
If I remove the disable="${myCheckbox.selected}"
from the FXML file, everything loads as expected. In addition, I am able to bind the properties in code. Why isn't this working, and how can I modify the FXML to support this? I am running on Windows 7 Enterprise SP1 x64, using Java SE JDK 8u92 x64.
It seems that you can't set the disabled property on the Spinner using FXML this way. It works fine on TextFields. It might be a bug, I guess it's something to do with the loader expecting a body for the Spinner tag defining the ValueFactory, so the Spinner isn't defined properly when the attempt to link the CheckBox state to the disable property is carried out.
The following workaround might help:
<?xml version="1.0" encoding="UTF-8"?>
<?language javascript?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.util.* ?>
<?import javafx.scene.*?>
<?import javafx.scene.control.* ?>
<?import javafx.scene.layout.* ?>
<?import javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory?>
<HBox xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1"
alignment="BASELINE_LEFT" spacing="15">
<fx:script>
function handleCheckBoxAction(event) {
mySpinner.disable = (! mySpinner.disabled);
}
</fx:script>
<children>
<CheckBox fx:id="myCheckbox" text="Disable?" mnemonicParsing="false" onAction="handleCheckBoxAction(event);" />
<Spinner fx:id="mySpinner">
<valueFactory>
<SpinnerValueFactory.IntegerSpinnerValueFactory min="0" max="10"/>
</valueFactory>
</Spinner>
</children>
</HBox>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With