JavaFX java.lang.IllegalArgumentException: 无法将 javafx.scene.control.Label 字段 sample.Controller.location 设置为 java.net.URL
JavaFX java.lang.IllegalArgumentException: Can not set javafx.scene.control.Label field sample.Controller.location to java.net.URL
我的 JavaFX 应用程序有一个 fx:id 为 location
的标签。它在 FXML 文件中定义。当我尝试 运行 应用程序时,出现以下错误:
java.lang.IllegalArgumentException: Can not set javafx.scene.control.Label field sample.Controller.location to java.net.URL
我正在使用 JDK 12 和 JavaFX 11.0.2。
我在 SO 上看到其他答案说这是由 location
标签的类型冲突引起的。例如,它可能在 FXML 文件中声明为标签,但在 Java 代码中它是其他东西(在本例中为 java.net.URL)。但是,正如您在下面的代码中看到的,我没有在任何地方使用 URL class。
将 fx:id 更改为其他名称(例如 loc
)会使错误消失,因此 location
必须是 "magic" 名称。
这是什么原因造成的?
sample.fxml
<?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>
Main.java
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;
}
模块-info.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
(如 resources
、controller
和 Controller
)是 保留关键字 。
这些关键字被添加到一个namespace
(一个可观察的地图:ObservableMap<String, Object> namespace
),而location
是FXML文件的URL,类似于:
namespace.put("location", "file:/path/to/your/FXML/file");
稍后,对 FXML 文件的不同 fx:id
标记进行评估并将其添加到同一命名空间:
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);
显然,由于您使用的是相同的密钥,因此您正在用一个新对象覆盖前一个 URL,在本例中是一个标签。
稍后,当 FXMLLoader 尝试注入此位置时:
injectFields(LOCATION_KEY, location);
发生异常,因为地图从键 "location"
获取的 Label
可以设置为 URL 字段:
Can not set javafx.scene.control.Label field org.openjfx.FXMLController.location to java.net.URL
虽然没有记录,这意味着您不能使用 "location"
(也不能使用 "resources"
、"controller"
)作为 fx:id
标签的值,因为它会和这些关键字发生冲突。
我的 JavaFX 应用程序有一个 fx:id 为 location
的标签。它在 FXML 文件中定义。当我尝试 运行 应用程序时,出现以下错误:
java.lang.IllegalArgumentException: Can not set javafx.scene.control.Label field sample.Controller.location to java.net.URL
我正在使用 JDK 12 和 JavaFX 11.0.2。
我在 SO 上看到其他答案说这是由 location
标签的类型冲突引起的。例如,它可能在 FXML 文件中声明为标签,但在 Java 代码中它是其他东西(在本例中为 java.net.URL)。但是,正如您在下面的代码中看到的,我没有在任何地方使用 URL class。
将 fx:id 更改为其他名称(例如 loc
)会使错误消失,因此 location
必须是 "magic" 名称。
这是什么原因造成的?
sample.fxml
<?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>
Main.java
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;
}
模块-info.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
(如 resources
、controller
和 Controller
)是 保留关键字 。
这些关键字被添加到一个namespace
(一个可观察的地图:ObservableMap<String, Object> namespace
),而location
是FXML文件的URL,类似于:
namespace.put("location", "file:/path/to/your/FXML/file");
稍后,对 FXML 文件的不同 fx:id
标记进行评估并将其添加到同一命名空间:
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);
显然,由于您使用的是相同的密钥,因此您正在用一个新对象覆盖前一个 URL,在本例中是一个标签。
稍后,当 FXMLLoader 尝试注入此位置时:
injectFields(LOCATION_KEY, location);
发生异常,因为地图从键 "location"
获取的 Label
可以设置为 URL 字段:
Can not set javafx.scene.control.Label field org.openjfx.FXMLController.location to java.net.URL
虽然没有记录,这意味着您不能使用 "location"
(也不能使用 "resources"
、"controller"
)作为 fx:id
标签的值,因为它会和这些关键字发生冲突。