场景生成器 - Jar导入问题

时间:2018-05-28 09:15:34

标签: javafx jar custom-controls scenebuilder

我问了很多关于Scene Builder的问题,我开始觉得我可能会对某些人产生轻微的烦恼。但现在又出现了另一个问题。我之前发布了this关于将嵌套自定义节点导入Scene Builder的问题。我穿着闪亮盔甲的骑士来了,帮我解决了这个问题。现在我遇到了一个新问题。症状完全相同,但原因似乎不同。再一次,我不知道如何测试这个问题(如果有人教我如何,我会很高兴。不幸的是,我不完全理解最后一个答案的错误测试方法。)但它似乎来自无处。

所以问题就像以前一样,当我尝试导入包含自定义节点的jar文件时,最外层容器中的其他嵌套节点不能导入到Scene Builder中。上次通过添加

解决了这个问题
fxmlLoader.setClassLoader(getClass().getClassLoader());
在加载fxml之前

到我的java控制器代码,但这次没有修复它。 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。我不相信changelisteners存在问题,因为从IDE运行时它们都能正常工作。

编辑3:请参阅下面的答案以获得更好的解释。我只想在我的源代码中添加它,NumberSlider需要所有属性的getter和setter,甚至是从NumberField继承的那些属性。否则它不会很好地与Scene Builder一起玩。

1 个答案:

答案 0 :(得分:3)

有一个简单的解决方法可以使嵌套控件正常工作并由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的三个控件。

另请注意,控件的预览将反映这些新的默认值。

Importing nested controls