- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我希望有人能够向我解释为什么 SceneBuilder 在导入自定义控件时如此不稳定。
以一个相对简单的自定义控件为例(仅作为示例):
public class HybridControl extends VBox{
final private Controller ctrlr;
public CustomComboBox(){
this.ctrlr = this.Load();
}
private Controller Load(){
final FXMLLoader loader = new FXMLLoader();
loader.setRoot(this);
loader.setClassLoader(this.getClass().getClassLoader());
loader.setLocation(this.getClass().getResource("Hybrid.fxml"));
try{
final Object root = loader.load();
assert root == this;
} catch (IOException ex){
throw new IllegalStateException(ex);
}
final Controller ctrlr = loader.getController();
assert ctrlr != null;
return ctrlr;
}
/*Custom Stuff Here*/
}
然后这里就有了 Controller 类:
public class Controller implements Initializable{
/*FXML Variables Here*/
@Override public void initialize(URL location, ResourceBundle resources){
/*Initialization Stuff Here*/
}
}
这工作得很好。 .jar 编译得很好,SceneBuilder 可以很好地读取 .jar,它可以很好地导入控件,这很棒。
令我烦恼的是,它需要两个单独的类来完成,这没什么大不了的,只是我觉得这应该只用一个类就可以实现。
我现在已经有了上面的方法,但我尝试了另外两种方法,但都失败了(SceneBuilder 找不到并让我导入控件),我希望有人能告诉我原因,以便我可以继续我的生活。
在第二种情况下,我尝试使用一个类来扩展 VBox 并实现可初始化:
public class Hybrid extends VBox implements Initializable{ /*In this case the FXML file Controller would be set to this class.*/
/*FXML Variables Here*/
public Hybrid(){
this.Load();
}
private void Load(){
final FXMLLoader loader = new FXMLLoader();
loader.setRoot(this);
loader.setClassLoader(this.getClass().getClassLoader());
loader.setLocation(this.getClass().getResource("Hybrid.fxml"));
try{
final Object root = loader.load();
assert root == this;
} catch (IOException ex){
throw new IllegalStateException(ex);
}
assert this == loader.getController();
}
@Override public void initialize(URL location, ResourceBundle resources){
/*Initialization Stuff Here*/
}
}
这对我来说非常有意义。它应该有效,至少在我看来,但事实并非如此。该 jar 编译得很好,我什至打赌它在程序中可以完美地工作,但是当我尝试将 .jar 导入到 Scene Builder 中时,它不起作用。它不存在于可导入控件列表中。
所以...我尝试了一些不同的东西。我尝试将 Controller 类嵌套在 Control 类中:
public class Hybrid extends VBox{ /*In this case the FXML Controller I had set to Package.Hybrid.Controller*/
final private Controller ctrlr
public Hybrid(){
this.ctrlr = this.Load();
}
private Controller Load(){
/*Load Code*/
}
public class Controller implements Initializable{
/*Controller Code*/
}
}
这也不起作用。我尝试了公共(public)、私有(private)、公共(public)静态、私有(private)静态,但都不起作用。
那么为什么会出现这种情况呢?为什么 SceneBuilder 无法识别自定义控件,除非 Control 类和 Controller 类是两个独立的实体?
感谢下面的 James_D,我能够得到答案并使自定义控件按照我想要的方式工作。如果类的名称与 FXML 文件的名称相同,我还能够创建适用于所有自定义类的通用 Load 方法:
private void Load(){
final FXMLLoader loader = new FXMLLoader();
String[] classes = this.getClass().getTypeName().split("\\.");
String loc = classes[classes.length - 1] + ".fxml";
loader.setRoot(this);
loader.setController(this);
loader.setClassLoader(this.getClass().getClassLoader());
loader.setLocation(this.getClass().getResource(loc));
try{
final Object root = loader.load();
assert root == this;
} catch (IOException ex){
throw new IllegalStateException(ex);
}
assert this == loader.getController();
}
只是想我会分享这一点。再次请注意,它仅在您的类名为 Hybrid 并且您的 FXML 文件名为 Hybrid.fxml 时才有效。
最佳答案
您的第二个(和第三个)版本根本无法工作(SceneBuilder 或没有 SceneBuilder),因为断言
this == loader.getController()
将会失败。当您调用 loader.load()
时,FXMLLoader
会看到 fx:controller="some.package.Hybrid"
并创建它的一个新实例。现在您有了 Hybrid
类的两个实例:一个在 FXMLLoader
上调用 load
,另一个被设置为加载的 FXML 的 Controller 。
您需要从 FXML 文件中删除 fx:controller
属性,并直接在代码中设置 Controller ,如 documentation 中所示。 :
private void Load(){
final FXMLLoader loader = new FXMLLoader();
loader.setRoot(this);
loader.setClassLoader(this.getClass().getClassLoader());
loader.setLocation(this.getClass().getResource("Hybrid.fxml"));
// add this line, and remove the fx:controller attribute from the fxml file:
loader.setController(this);
try{
final Object root = loader.load();
assert root == this;
} catch (IOException ex){
throw new IllegalStateException(ex);
}
assert this == loader.getController();
}
使用 SceneBuilder 进行实验,它似乎会尝试通过调用无参数构造函数来创建自定义控件,并期望在不创建异常的情况下完成。在这种特定情况下,它似乎无法正确处理注入(inject) @FXML
带注释的值。我建议在 jira 提交错误为了这。
作为解决方法,您可能必须编写代码,以便即使未注入(inject) @FXML
注释字段,也能完成无参数构造函数的执行,而不会引发异常。 (是的,这很痛苦。)
关于java - 为什么 SceneBuilder 对自定义控件如此讲究?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26243900/
我是 JavaFX 的新手,我还没有找到关于这个问题的任何教程/答案。 所以基本上我想做的只是改变我场景的一部分。我想在顶部保留一个静态菜单栏,仅根据单击的菜单按钮更改底部。这意味着我需要为每个“页面
在我的 JavaFX 应用程序中,某些节点显示在预览中,但不可选择,也不会显示在层次结构中。 SceneBuilder 不可定位示例: 在此示例中,“名字”列不可定位,并且不会显示在层次结构中,即使它
我在使用场景生成器时遇到了奇怪的渲染问题,但前提是我从 ControlsFX 导入了 JAR。 正如您在以下视频中看到的: https://www.youtube.com/watch?v=dD1euL
我创建了这个自定义组件: public class IconButton extends Button { @FXML private ImageView imageView; pri
我下载了 Scene Builder,并尝试打开 .fxml 文件,但出现以下错误消息: Failed to launch SceneBuilder. The error message was: C
我刚刚从 Gluon 安装了 SceneBuilder,但无法启动它...它安装正确(我注意到安装程序没有到达末尾...但所有文件都在 AppData/Local 中正确)我尝试启动 EXE 但它不会
我安装了 SceneBuilder 8.3.0在安装了Java Hotspot 1.8.0_131的Ubuntu Gnome 17.04上,尝试启动时出现错误,无法初始化。我已经尝试安装Oracle的
不确定这是不是该问的地方。如果有更好的 SE 站点,请告诉我。 自从我开始使用 SceneBuilder 以来,它的子菜单就完全无法使用,因为一旦我移动光标选择一个选项,它们就会消失。 例如 - 假设
我对 SceneBuilder 和 Java FX 处理自定义控件的方式束手无策。 我是使用 fx:root,还是不使用它?我选择使用它。所以在控件的Controller+Root类,我把自己设置为r
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 4 年前。
在 JavaFX 中存在控件 ToggleGroup 。我已经安装了SceneBuilder,版本: Product Version JavaFX Scene Builder 8.0.0 Build
我的问题是,如何在 JavaFX 中根据应用程序窗口的大小实现在操作过程中自动调整图像大小?这可以直接在 SceneBuilder 中完成吗? 最佳答案 它将其 WidthProperty 和 Hei
我需要用 SceneBuilder 创建一个 GUI。我在我的界面中添加了一个 ImageView 并正确设置了我的图像的路径。图像显示在 SceneBuilder 中,但是当我运行我的应用程序时,图
这就是我正在尝试做的事情: 我想要一个显示 31 个 Pane 的场景,然后将用红色或绿色填充它们。 (点击它们应该改变颜色) 我现在想知道实现这一点的最佳方法是什么。我首先想到了 TableView
我在 SceneBuilder 打开我的 main.fxml 时遇到问题。当我运行项目时一切正常,但我无法在 SceneBuilder 下进行修改。每次我想添加到 main.fxml 时,我都需要删除
我正在使用 SceneBuilder 构建 javaFX 应用程序,问题是,当我在 fxml 文件中指定相对路径时,它会在运行时抛出异常: null/../images/text_formal.png
我正在尝试使用场景生成器创建的按钮切换场景。 这是我的 Controller 类 public class Controller implements Initializable { @FXM
我有一个非常简单的类,它获取作业列表并尝试用它们填充 TableView。我在不使用 FXML 的情况下完成了这项工作,但我现在正在尝试新方法。我遇到的问题是; tView.getItems().ad
我试图在 SceneBuilder 中重新创建库列表的外观,但我不知道我需要采用哪个元素。 如何重新创建此列表? 最佳答案 这是使用 ControlsFx Awesome Fonts 的草稿。 Mai
我希望有人能够向我解释为什么 SceneBuilder 在导入自定义控件时如此不稳定。 以一个相对简单的自定义控件为例(仅作为示例): public class HybridControl exten
我是一名优秀的程序员,十分优秀!