当前位置: 首页 > 知识库问答 >
问题:

带有FXML的JavaFX UI控件架构(控制皮肤)

卫子平
2023-03-14

在JavaFX8中,有一个UI控件体系结构,用于创建自定义控件。基本上是基于:

  • 控制。
  • 皮肤。
  • 新浪网.

此外,还有一个FXML项目的基本结构,也用于制作GUI。基本上:

  • 控制。
  • FXML 文件。
  • 新浪网.

我想将FXML与UI控件架构一起使用,所以我的问题是:

谁是FXML文件的控制器?皮肤?

我必须执行以下代码之类的操作?:

public class MySkin extends SkinBase<MyControl> {
public GaugeSkin(MyControl control) {
    super(control);
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MyView.fxml"));
    fxmlLoader.setRoot(control);
    fxmlLoader.setController(control);

    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

共有2个答案

艾敏学
2023-03-14

我更好的方法:

  • 消除对<code>的需求

一个合适的Control类。

public static class ControlName extends Control {
    @Override
    protected Skin<?> createDefaultSkin() {
        ControlNameSkin.Factory factory = new ControlNameSkin.Factory(this);
        FXMLLoader fxmlLoader = new FXMLLoader(getClass()
                 .getResource("ControlName.fxml"));
        fxmlLoader.setControllerFactory(factory);
        try {
            Node root = fxmlLoader.load();
            ControlNameSkin skin = fxmlLoader.getController();
            skin.construct(root);
            return skin;
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }
}

组合的皮肤和控制器类。

public static class ControlNameSkin extends SkinBase<ControlName> {
    public ControlNameSkin(Factory factory) {
        super(factory.control);
        // any setup NOT using FXML references
    }

    public void construct(Node root) {
        ControlName control = getSkinnable();
        // any setup using FXML references
        getChildren().add(root);
    }

    public static class Factory implements Callback<Class<?>, Object> {
        public final ControlName control;

        public Factory(ControlName control) {
            this.control = control;
        }

        @Override
        public Object call(Class<?> cls) {
            try {
                return cls.getConstructor(Factory.class).newInstance(this);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }
    }
}
申屠无尘
2023-03-14

我认为< code>Skin类作为加载的FXML文件的控制器是正确的,因为正是< code>Skin负责定义构成特定控件“外观”的节点。

Control 类本身实际上应该只定义保存控件状态的属性,而不应该关心 Skin 实际创建视图层次结构的方式(也就是说,它应该只关心它的状态,而不应该关心它的外观)。

我要做的一个区别是将fxmlloader.setController(control);更改为fxmlloader.setController(this);以便Skin类成为控制器而不是控件本身。

您可以做的另一件事是将FXMLLoader逻辑移动到基类中,这样您就不必在每次想要创建Skin时复制它,如下所示:

public abstract class FXMLSkin<C extends Control> extends SkinBase<C>{

    public FXMLSkin(C control) {
        super(control);
        this.load();
    }

    private void load() {
        FXMLLoader loader = new FXMLLoader(getFXML());
        loader.setController(this);

        try {
            Node root = loader.load();
            this.getChildren().add(root);
        } catch (IOException ex) {
            Logger.getLogger(FXMLSkin.class.getName()).log(Level.SEVERE, null, ex);
        }   
    }

    protected abstract URL getFXML();
}

我的Github页面上有一个JavaFX UserControl,它做的事情与上面的< code>FXMLSkinBase类非常相似。它使用一个约定来加载与派生类同名的FXML文件,这样就不需要每次都指定FXML文件名。例如,如果您的派生皮肤名为< code>FooControlSkin,控件将自动加载名为< code>FooControlSkin.fxml的FXML文件。

该类非常简单,代码可以很容易地重构为一个满足您需求的功能全面的< code>FXMLSkinBase类。

 类似资料:
  • 我已经找到了一堆关于这个主题的帖子,但是我仍然无法将一个对象从Controller1传递到Controller2。有没有一个完整的教程或一些例子项目这样做? 我已经走了这么远,直到我被卡住了: 国家类 很抱歉这么长的帖子,我试图尽可能完整,否则我永远不会明白...

  • 问题内容: 我试图在JavaFX中获得TableView来动态显示内容。 当我运行程序时,出现此错误: 我的控制器名为“ UserInterfaceController.java”,它与FXML文件位于同一软件包下,我也已将该软件包导入了FXML中。为什么找不到控制器? FXML文件: 控制器: 主类: 问题答案: 使用FXML的全限定名来引用您的控制器: 后续问题的答案 对以下问题的回答解释了为

  • 我试图在JavaFX中获得一个TableView来动态显示内容。 当我运行程序时,出现以下错误: 我的控制器名为“UserInterfaceController.java”,它与FXML文件在同一个包下,我也在FXML中导入了包。为什么找不到控制器? FXML文件: 控制器: 主要类:

  • 某个 shard 分配在哪个节点上,一般来说,是由 ES 自动决定的。以下几种情况会触发分配动作: 新索引生成 索引的删除 新增副本分片 节点增减引发的数据均衡 ES 提供了一系列参数详细控制这部分逻辑: cluster.routing.allocation.enable 该参数用来控制允许分配哪种分片。默认是 all。可选项还包括 primaries 和 new_primaries。none 则

  • 当我想在Intellij JPA控制台中进行查询时,我得到的错误是,