使用 FXML 的 JavaFX UI 控件架构(控件+皮肤)

mul*_*080 5 java model-view-controller custom-controls fxml javafx-8

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

  • 控制。
  • 皮肤。
  • CSS。

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

  • 控制。
  • FXML 文件。
  • CSS。

我想将 FXML 与UI Controls Architecture一起使用,所以我的问题是:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Ben*_*ale 5

我认为您的思路是正确的,该类Skin是加载的 FXML 文件的控制器,因为它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();
}
Run Code Online (Sandbox Code Playgroud)

我的 Github 页面上有一个JavaFXUserControl,它的功能与FXMLSkinBase上面的类非常相似。它使用约定来加载与派生类同名的 FXML 文件,这样就不需要每次都指定 FXML 文件名。如果你的IE派生皮肤被调用FooControlSkin,该控件会自动加载一个名为.fxml的FXML文件FooControlSkin.fxml

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