JavaFX java.lang.IllegalArgumentException : Can not set javafx. scene.control.Label 字段 sample.Controller.location 到 java.net.URL

原文 标签 java javafx fxml

我的 JavaFX 应用程序有一个标签,其 fx:id 为 location .它在 FXML 文件中定义。当我尝试运行该应用程序时,出现以下错误:

java.lang.IllegalArgumentException: Can not set javafx.scene.control.Label field sample.Controller.location to java.net.URL



我在 JavaFX 11.0.2 中使用 JDK 12。

我在 SO 上看到了其他答案,说这是由 location 的冲突类型引起的标签。例如,它可能在 FXML 文件中被声明为 Label,但在 Java 代码中它是其他东西(在本例中为 java.net.URL)。但是,正如您在下面的代码中看到的,我没有在任何地方使用 URL 类。

将 fx:id 更改为其他内容(例如 loc )会使错误消失,因此 location必须是一个“神奇”的名字。

这是什么原因造成的?

示例文件
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Pane?>

<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <children>
      <Label fx:id="location" layoutX="133.0" layoutY="146.0" text="Output" />
   </children>
</Pane>

主程序
package sample;

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
{

    @Override
    public void start(Stage primaryStage) throws Exception
    {
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 400, 275));
        primaryStage.show();
    }


    public static void main(String[] args)
    {
        launch(args);
    }
}

Controller .java
package sample;

import javafx.fxml.FXML;
import javafx.scene.control.Label;

public class Controller
{
    @FXML
    Label location;

}

模块信息.java
module MyTest
{
    requires javafx.controls;
    requires javafx.fxml;
    opens sample;
}

最佳答案

通过检查 FXMLLoader 比较容易发现:

/**
 * A key for location URL in namespace map.
 * @see #getNamespace()
 * @since JavaFX 2.2
 */
public static final String LOCATION_KEY = "location";
/**
 * A key for ResourceBundle in namespace map.
 * @see #getNamespace()
 * @since JavaFX 2.2
 */
public static final String RESOURCES_KEY = "resources";

private URL location;
private ResourceBundle resources;

private <T> T loadImpl(InputStream inputStream,
                       Class<?> callerClass) throws IOException {
    ...
    namespace.put(LOCATION_KEY, location);
    namespace.put(RESOURCES_KEY, resources);
    ...
}

基本上这意味着 location (如 resourcescontrollerController )是保留关键字。

这些关键字被添加到 namespace (可观察 map : ObservableMap<String, Object> namespace )和 location是 FXML 文件的 URL,类似于:
namespace.put("location", "file:/path/to/your/FXML/file");

后来,不同的fx:id FXML 文件的标签被评估并添加到相同的命名空间:
private void processValue() throws LoadException {
    ...
    if (fx_id != null) {
        namespace.put(fx_id, value);
        injectFields(fx_id, value);
    }
    ...
}

在这种情况下,如果您的 fx:id"location" ,您将执行以下操作:
namespace.put("location", Label@12dafafa);

显然,由于您使用相同的 key ,因此您将使用新对象(在本例中为 Label)覆盖之前的 URL。

稍后,当 FXMLLoader 尝试注入(inject)此位置时:
injectFields(LOCATION_KEY, location);

异常发生,因为 Label map 从 key "location" 中获取可以设置为 URL 字段:
Can not set javafx.scene.control.Label field org.openjfx.FXMLController.location to java.net.URL

虽然没有记录,但这意味着您不能使用 "location" (也不是 "resources""controller" )作为 fx:id 的值标签,因为它会与这些关键字发生冲突。

关于JavaFX java.lang.IllegalArgumentException : Can not set javafx. scene.control.Label 字段 sample.Controller.location 到 java.net.URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56247046/

相关文章:

打包后JavaFX对图像抛出错误

java - 在多屏幕设置中的 Activity 屏幕或监视器上打开 JavaFX 应用程序

JavaFX 8 Spinner 控件不更新显示的值

java - FXML如何设置选择框默认值

java - 在 jsoup 选择器中使用逻辑或、非和和

Java-多边形和线的交点

java - 从 Map 中获取 Java 中特定键的 Long 值列表

java - Java构造函数和初始化类变量

java - 删除 GridPane 中某个类型的所有节点

JavaFX 8 将多个 fxml 文件加载到边框 Pane 中