java 自定义 JavaFX 控件 - Scene Builder 2.0 中的“已指定根值”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25733847/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Custom JavaFX control - "root value already specified" in Scene Builder 2.0
提问by Cy?egha
I have implemented a custom control, using an fxml file and a Java class, similar to what is explained in this official tutorial(see the code bellow). Note that the fxml root element is defined with fx:root
and I call setRoot
programmatically.
我已经使用 fxml 文件和 Java 类实现了一个自定义控件,类似于本官方教程中解释的内容(请参阅下面的代码)。请注意,fxml 根元素是用程序定义的fx:root
,我以setRoot
编程方式调用。
I have tried including the control in the FXML layout of an application, and the application loads fine (and displays the control as expected).
我尝试在应用程序的 FXML 布局中包含控件,并且应用程序加载良好(并按预期显示控件)。
However, if I try to import a jar file containing my control in Scene Builder 2.0, the control doesn't appear in the list of components to import (unlike some other controls in the same jar). If I select "Show JAR Analysis Report", it shows an error caused by javafx.fxml.LoadException: Root value already specified
.
但是,如果我尝试在 Scene Builder 2.0 中导入包含我的控件的 jar 文件,则该控件不会出现在要导入的组件列表中(与同一 jar 中的某些其他控件不同)。如果我选择“显示 JAR 分析报告”,它会显示由javafx.fxml.LoadException: Root value already specified
.
Do you know why I get this error when loading in Scene Builder, even though it loads correctly in a real application?
您知道为什么在 Scene Builder 中加载时会出现此错误,即使它在实际应用程序中正确加载吗?
Here is the FXML :
这是 FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<fx:root type="javafx.scene.layout.GridPane" id="MediaMetadataDisplay" hgap="20.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0"
prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<columnConstraints>
<ColumnConstraints fillWidth="false" hgrow="NEVER" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="200.0"/>
<ColumnConstraints halignment="LEFT" hgrow="ALWAYS"/>
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="40.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="25.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="25.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="25.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="25.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<ImageView id="coverView" fx:id="coverView" fitHeight="200.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" GridPane.rowSpan="7"/>
<Label id="trackName" fx:id="trackName" maxWidth="1.7976931348623157E308" text="trackName" GridPane.columnIndex="1" GridPane.rowIndex="1">
<font>
<Font name="System Bold" size="16.0"/>
</font>
</Label>
<Label id="artist" fx:id="artist" maxWidth="1.7976931348623157E308" text="artist" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
<Label id="album" fx:id="album" maxWidth="1.7976931348623157E308" text="album" GridPane.columnIndex="1" GridPane.rowIndex="3"/>
<Label id="genre" fx:id="genre" maxWidth="1.7976931348623157E308" text="genre" GridPane.columnIndex="1" GridPane.rowIndex="4"/>
<Label id="trackNumber" fx:id="trackNumber" maxWidth="1.7976931348623157E308" text="trackNumber" GridPane.columnIndex="1" GridPane.rowIndex="5"/>
</children>
</fx:root>
And the Java controller/root element:
和 Java 控制器/根元素:
package customjavafx.scene.control;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.media.Media;
import java.io.IOException;
import java.util.Map;
public class MediaMetadataDisplay extends GridPane {
public MediaMetadataDisplay() {
final FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MediaMetadataDisplay.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
media.addListener((obs, oldVal, newVal) -> updateMedia(newVal));
}
private final ObjectProperty<Media> media = new SimpleObjectProperty<>((Media) null, "media");
@FXML private ImageView coverView;
@FXML private Label trackName;
@FXML private Label artist;
@FXML private Label album;
@FXML private Label genre;
@FXML private Label trackNumber;
public void updateMedia(Media media) {
// TODO show updated metadata
}
public ObjectProperty<Media> mediaProperty() {
return media;
}
public Media getMedia() {
return mediaProperty().get();
}
public void setMedia(final Media media) {
mediaProperty().set(media);
}
}
The cause of the error, in the stacktrace shown by Scene Builder :
错误的原因,在 Scene Builder 显示的堆栈跟踪中:
Caused by: javafx.fxml.LoadException: Root value already specified.
file:/Users/guillaumegaly/Library/Application%20Support/Scene%20Builder/Library/custom-controls_2.11.jar!/customjavafx/scene/control/MediaMetadataDisplay.fxml
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2613)
at javafx.fxml.FXMLLoader.createElement(FXMLLoader.java:2771)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2720)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
at customjavafx.scene.control.MediaMetadataDisplay.<init>(MediaMetadataDisplay.java:26)
... 18 more
回答by swapyonubuntu
Remove the line
删除该行
fxmlLoader.setRoot(this);
Your FXML defines the root to be an AnchorPane (and you can't set the root twice, which is why you are getting the error).
您的 FXML 将根定义为 AnchorPane(并且您不能将根设置两次,这就是您收到错误的原因)。
<fx:root type="javafx.scene.layout.GridPane" id="MediaMetadataDisplay" hgap="20.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0"
prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
I am really thankful to this post
我真的很感谢这篇文章
回答by Dean Irwin
I was following the Javafx FXML tutorials on the documentation, and I got stuck on the custom components section. The problem for me was that when I called the setRoot method, it would throw a "Root already specified" error. Personally, I fixed this by adding the root tag into the custom component FXML document. It now works.
我一直在关注文档上的 Javafx FXML 教程,但卡在了自定义组件部分。我的问题是,当我调用 setRoot 方法时,它会抛出“Root 已指定”错误。就个人而言,我通过将根标记添加到自定义组件 FXML 文档中来解决此问题。它现在可以工作了。
I'm adding this so that if someone else has the same issue, Google can give them the answer.
我添加这个是为了如果其他人有同样的问题,谷歌可以给他们答案。