Scene Builder - Jar 导入问题
Scene Builder - Jar Import Issue
我问了很多关于 Scene Builder 的问题,以至于我开始觉得我对某些人来说可能有点烦人。但现在另一个问题暴露了出来。我之前发布了 有关将嵌套自定义节点导入 Scene Builder 的问题。我身穿闪亮盔甲的骑士过来帮我解决了这个问题。现在我有一个新问题。症状完全相同,但原因似乎不同。我再次不知道如何对这个问题进行错误测试(如果有人教我怎么做,我会很高兴。不幸的是,我不完全理解最后一个答案的错误测试方法。)但它似乎无处不在。
所以问题是,就像以前一样,当我尝试导入一个包含自定义节点的 jar 文件时,最外层容器中的其他嵌套节点没有导入到 Scene Builder 中。上次通过添加
解决了这个问题
fxmlLoader.setClassLoader(getClass().getClassLoader());
到我的 java 控制器代码,然后再加载 fxml,但这一次没有修复它。 Here是所有的源代码。老实说,这个问题可能很愚蠢,我忽略了,如果是这样,我提前道歉。
感谢大家的帮助!
编辑: 我应该声明所有罐子 运行 本身都很好。他们只是不能很好地使用 Scene Builder。
编辑 2: 正如评论中所指出的,我应该尽量让问题更容易理解,对此我深表歉意。所以这是结构。最外面的组件是我所说的 NumberSlider。这包含另外两个自定义组件 NumberField 和 InfoIcon(见下图)。内部组件是进口的,外部不是。 NumberSlider 的结构基本上是一个滑块,它的 valueProperty 绑定到 NumberField 的 valueProperty。 NumberField 本质上是一个 TextField,它允许用户输入文本以更改其 valueProperty,如果 valueProperty 发生更改,文本也会更改以匹配此内容。我认为问题出在滑块变量的制作上,因为这是未按应有的方式导入的组件。这是构造函数。
//Properties
private final BooleanProperty logarithmic;
private final BooleanProperty ticks;
//Variables
@SuppressWarnings("unused")
private boolean lock = false;
//Structural Elements
@FXML private Label label;
@FXML private Slider slider;
@FXML public NumberField field;
@FXML private InfoIcon info;
public NumberSlider(@NamedArg("logarithmic") boolean logarithmic, @NamedArg("ticks") boolean ticks,
@NamedArg("intSlider") boolean intSlider, @NamedArg("value") double value,
@NamedArg("min") double min, @NamedArg("max") double max) {
this.logarithmic = new SimpleBooleanProperty(this, "logarithmic", logarithmic);
this.ticks = new SimpleBooleanProperty(this, "ticks", ticks);
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("NumberSlider.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
fxmlLoader.setClassLoader(getClass().getClassLoader());
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
field.reconfigureLogic(value, min, max, intSlider);
//An awfully long code block that basically binds the two properties with change listeners in different ways depending on the input arguments.
}
NumberSlider 的其余部分只是其各种属性的 getter 和 setter。我不认为更改监听器有问题,因为当从我的 IDE.
中 运行ning 时它们都工作正常
编辑 3: 请参阅下面的答案以获得很好的解释。我只想在我的源代码中添加一点,NumberSlider 的所有属性都需要 getter 和 setter,甚至是那些从 NumberField 继承的属性。否则它不会很好地与 Scene Builder 一起播放。
有一个简单的修复程序可以让您的嵌套控件正常工作并由 Scene Builder 导入。
此问题与您用于控件的非空构造函数有关。
虽然 NumberField
使用此构造函数工作(因为它可以导入):
public NumberField(@NamedArg("intField") boolean intField, @NamedArg("value") double value, @NamedArg("min") double min,
@NamedArg("max") double max);
外部控件 NumberSlider
,它使用 NumberField
控件,并具有此构造函数:
public NumberSlider(@NamedArg("logarithmic") boolean logarithmic, @NamedArg("ticks") boolean ticks,
@NamedArg("intSlider") boolean intSlider, @NamedArg("value") double value,
@NamedArg("min") double min, @NamedArg("max") double max);
导入失败
这次不是类加载器问题,而是与参数和相关默认值有关的问题。
@NamedArg 默认值
那么,当您从 Scene Builder 创建控件实例时,这些参数的默认值是多少?
- 对于布尔值:
false
- 对于整数:
0
- 双打:
0.0
这意味着当您创建一个控件时,您正在调用:
final NumberSlider slider = new NumberSlider(false, false, false, 0, 0, 0);
如果你在你的项目上尝试这样做,它会失败!!
Caused by: java.lang.IllegalArgumentException: MajorTickUnit cannot be less than or equal to 0.
at javafx.scene.control.Slider.setMajorTickUnit(Slider.java:397)
at com.mycompany.numberslider.NumberSlider.<init>(NumberSlider.java:118)
at com.mycompany.numberslider.NumberSliderApp.start(NumberSliderApp.java:20)
因为这个异常,控件从Scene Builder导入失败。
现在我们已经找到了问题,您有两种解决方法:
- 修改您的代码以允许这些默认值
- 修改namedArgs默认值
我将解释如何做后者,这将是我的首选。
但请注意,无论何时用户选择无效值,您都必须修改代码以避免 运行 控件出现问题。
@NamedArg defaultValue() 方法
如果检查 NamedArg
注释:
@Retention(RUNTIME)
@Target(PARAMETER)
public @interface NamedArg {
/**
* The name of the annotated argument.
* @return the name of the annotated argument
*/
public String value();
/**
* The default value of the annotated argument.
* @return the default value of the annotated argument
*/
public String defaultValue() default "";
}
有两种方法,通常我们只使用一种:value()
.
但我们可以同时使用两者并修改默认的 ""
值,如下所示:
public NumberSlider(@NamedArg(value="logarithmic", defaultValue="false") boolean logarithmic,
@NamedArg(value="ticks", defaultValue="false") boolean ticks,
@NamedArg(value="intSlider", defaultValue="false") boolean intSlider,
@NamedArg(value="value", defaultValue="50") double value,
@NamedArg(value="min", defaultValue="0") double min,
@NamedArg(value="max", defaultValue="100") double max);
进行此更改后,构建您的控件和 jar,然后尝试再次导入它,现在您将在 Scene Builder 中看到这三个控件。
另请注意,控件的预览将反映这些新的默认值。
我问了很多关于 Scene Builder 的问题,以至于我开始觉得我对某些人来说可能有点烦人。但现在另一个问题暴露了出来。我之前发布了
所以问题是,就像以前一样,当我尝试导入一个包含自定义节点的 jar 文件时,最外层容器中的其他嵌套节点没有导入到 Scene Builder 中。上次通过添加
解决了这个问题fxmlLoader.setClassLoader(getClass().getClassLoader());
到我的 java 控制器代码,然后再加载 fxml,但这一次没有修复它。 Here是所有的源代码。老实说,这个问题可能很愚蠢,我忽略了,如果是这样,我提前道歉。
感谢大家的帮助!
编辑: 我应该声明所有罐子 运行 本身都很好。他们只是不能很好地使用 Scene Builder。
编辑 2: 正如评论中所指出的,我应该尽量让问题更容易理解,对此我深表歉意。所以这是结构。最外面的组件是我所说的 NumberSlider。这包含另外两个自定义组件 NumberField 和 InfoIcon(见下图)。内部组件是进口的,外部不是。 NumberSlider 的结构基本上是一个滑块,它的 valueProperty 绑定到 NumberField 的 valueProperty。 NumberField 本质上是一个 TextField,它允许用户输入文本以更改其 valueProperty,如果 valueProperty 发生更改,文本也会更改以匹配此内容。我认为问题出在滑块变量的制作上,因为这是未按应有的方式导入的组件。这是构造函数。
//Properties
private final BooleanProperty logarithmic;
private final BooleanProperty ticks;
//Variables
@SuppressWarnings("unused")
private boolean lock = false;
//Structural Elements
@FXML private Label label;
@FXML private Slider slider;
@FXML public NumberField field;
@FXML private InfoIcon info;
public NumberSlider(@NamedArg("logarithmic") boolean logarithmic, @NamedArg("ticks") boolean ticks,
@NamedArg("intSlider") boolean intSlider, @NamedArg("value") double value,
@NamedArg("min") double min, @NamedArg("max") double max) {
this.logarithmic = new SimpleBooleanProperty(this, "logarithmic", logarithmic);
this.ticks = new SimpleBooleanProperty(this, "ticks", ticks);
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("NumberSlider.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
fxmlLoader.setClassLoader(getClass().getClassLoader());
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
field.reconfigureLogic(value, min, max, intSlider);
//An awfully long code block that basically binds the two properties with change listeners in different ways depending on the input arguments.
}
NumberSlider 的其余部分只是其各种属性的 getter 和 setter。我不认为更改监听器有问题,因为当从我的 IDE.
中 运行ning 时它们都工作正常编辑 3: 请参阅下面的答案以获得很好的解释。我只想在我的源代码中添加一点,NumberSlider 的所有属性都需要 getter 和 setter,甚至是那些从 NumberField 继承的属性。否则它不会很好地与 Scene Builder 一起播放。
有一个简单的修复程序可以让您的嵌套控件正常工作并由 Scene Builder 导入。
此问题与您用于控件的非空构造函数有关。
虽然 NumberField
使用此构造函数工作(因为它可以导入):
public NumberField(@NamedArg("intField") boolean intField, @NamedArg("value") double value, @NamedArg("min") double min,
@NamedArg("max") double max);
外部控件 NumberSlider
,它使用 NumberField
控件,并具有此构造函数:
public NumberSlider(@NamedArg("logarithmic") boolean logarithmic, @NamedArg("ticks") boolean ticks,
@NamedArg("intSlider") boolean intSlider, @NamedArg("value") double value,
@NamedArg("min") double min, @NamedArg("max") double max);
导入失败
这次不是类加载器问题,而是与参数和相关默认值有关的问题。
@NamedArg 默认值
那么,当您从 Scene Builder 创建控件实例时,这些参数的默认值是多少?
- 对于布尔值:
false
- 对于整数:
0
- 双打:
0.0
这意味着当您创建一个控件时,您正在调用:
final NumberSlider slider = new NumberSlider(false, false, false, 0, 0, 0);
如果你在你的项目上尝试这样做,它会失败!!
Caused by: java.lang.IllegalArgumentException: MajorTickUnit cannot be less than or equal to 0.
at javafx.scene.control.Slider.setMajorTickUnit(Slider.java:397)
at com.mycompany.numberslider.NumberSlider.<init>(NumberSlider.java:118)
at com.mycompany.numberslider.NumberSliderApp.start(NumberSliderApp.java:20)
因为这个异常,控件从Scene Builder导入失败。
现在我们已经找到了问题,您有两种解决方法:
- 修改您的代码以允许这些默认值
- 修改namedArgs默认值
我将解释如何做后者,这将是我的首选。
但请注意,无论何时用户选择无效值,您都必须修改代码以避免 运行 控件出现问题。
@NamedArg defaultValue() 方法
如果检查 NamedArg
注释:
@Retention(RUNTIME)
@Target(PARAMETER)
public @interface NamedArg {
/**
* The name of the annotated argument.
* @return the name of the annotated argument
*/
public String value();
/**
* The default value of the annotated argument.
* @return the default value of the annotated argument
*/
public String defaultValue() default "";
}
有两种方法,通常我们只使用一种:value()
.
但我们可以同时使用两者并修改默认的 ""
值,如下所示:
public NumberSlider(@NamedArg(value="logarithmic", defaultValue="false") boolean logarithmic,
@NamedArg(value="ticks", defaultValue="false") boolean ticks,
@NamedArg(value="intSlider", defaultValue="false") boolean intSlider,
@NamedArg(value="value", defaultValue="50") double value,
@NamedArg(value="min", defaultValue="0") double min,
@NamedArg(value="max", defaultValue="100") double max);
进行此更改后,构建您的控件和 jar,然后尝试再次导入它,现在您将在 Scene Builder 中看到这三个控件。
另请注意,控件的预览将反映这些新的默认值。