Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX Binding Fails with "Cannot bind to untyped object."

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.

like image 694
Jeff G Avatar asked Mar 29 '16 19:03

Jeff G


1 Answers

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>
like image 101
Geoff Avatar answered Jan 03 '23 15:01

Geoff