创建 GWT 组件

创建自定义小部件集

Jmix 框架在 jmix-ui-widgets-compiled 制件中提供一组编译好的小部件集。

如需在项目中创建自定义的小部件集,请按照下列步骤:

  1. 删除 implementation 'io.jmix.ui:jmix-ui-widgets-compiled' 依赖。

  2. build.gradle 添加下列依赖:

    implementation 'io.jmix.ui:jmix-ui-widgets' (1)
    widgets 'io.jmix.ui:jmix-ui-widgets'
    1 仅开发自定义客户端组件需要。
  3. 添加 compileWidgets 任务(根据你的应用程序包路径修改):

    compileWidgets {
        generate "ui.ex1.widgets.CustomWidgetSet"
        includePaths('**/io/jmix/**/widget/**', '**/ui/ex1/widgets/**')
    }

    如果某些界面修改了,但是不希望重新编译小部件集,则可以使用 compileWidgets 任务的 excludePathsincludePaths 参数。

    excludePaths 参数用于在编译小部件集的过程中排除某些路径或文件。示例:

    compileWidgets {
        generate 'com.company.demo.widgets.CustomWidgetSet'
        excludePaths('**/com/company/demo/**')
    }

    这样,com.company.demo 包内的改动不会触发小部件集的编译。

    includePaths 参数用于在编译小部件集的过程中包含某些路径或文件。示例:

    compileWidgets {
        generate 'com.company.demo.widgets.CustomWidgetSet'
        includePaths('**/io/jmix/**/widget/**', '**/com/company/demo/widgets/**')
    }

    这样,com.company.demo.widgets 包内的改动和任何 io.jmix 包下 widget 包(包括子包)内的改动都会触发小部件集的编译。其他地方的改动,例如,界面控制器或者 XML 描述的改动不会触发编译。如果遇到意料之外的重编译,使用 --info 参数执行 compileWidgets 可以查看特定原因。

    excludePathsincludePaths 参数都支持字符串格式的列表。

    格式可以包含:

    • * 匹配任意长度的字符。

    • ? 匹配单一字符。

    • ** 匹配任意目录或文件。

    格式中可以使用 '/''\' 作为文件目录分隔符。

    例如,includePaths('**/com/company/demo/widgets/**') 包含 com/company/demo/widgets 文件夹及其子文件夹内的所有文件。

  4. application.properties 文件添加 jmix.ui.widget-set 属性(根据上面 compileWidgets 任务修改路径):

    jmix.ui.widget-set=ui.ex1.widgets.CustomWidgetSet

小部件集通过名为 compileWidgetsWidgetsCompile 类型任务编译。使用 Jmix 插件会自动创建。

编译完成的小部件集位于 build/widgets 目录,并包含在项目的 JAR/WAR 制件中。

创建 ColorButton GWT 组件

在本节中,我们将创建一个自定义的 ColorButton 组件。该组件直接继承 JmixButton 组件。

自定义 UI 组件(即直接继承自 Vaadin 组件的组件)应放在 widgets 子包中,例如,com.company.sample.widgets。客户端组件(连接器和小部件),以及用于服务器端和客户端通信的类,例如 RPC 和状态类,应该放在 widgets.client 子包中,例如 com.company.sample.widgets.client。有关“客户端-服务器”集成的更多信息,请参阅 Vaadin 文档

创建组件状态类

widgets.client 包中创建 ColorButtonState.java

ColorButtonState 状态类定义了客户端和服务器之间发送的数据。其中包含 public 字段,用于在服务器端自动序列化并在客户端反序列化。

ColorButtonState.java
public class ColorButtonState extends JmixButtonState {

    public String color = "";
}

创建 Vaadin 组件类

ColorButton 是一个 Vaadin 组件类,可以为服务端代码、访问器方法、事件监听器和数据源连接定义 API。开发人员在应用程序代码中使用此类的方法。

widgets 包中创建 ColorButton.java

ColorButton.java
public class ColorButton extends JmixButton {

    @Override
    protected ColorButtonState getState() {
        return (ColorButtonState) super.getState();
    }

    @Override
    protected ColorButtonState getState(boolean markAsDirty) {
        return (ColorButtonState) super.getState(markAsDirty);
    }

    public String getColor() {
        return getState(false).color;
    }

    public void setColor(String color) {
        if (!Objects.equals(getState(false).color, color)) {
            getState().color = color;
        }
    }
}

创建连接器

widgets.client 包中创建 ColorButtonConnector.java

ColorButtonConnector 连接器将客户端代码与服务器链接。

ColorButtonConnector.java
@Connect(ColorButton.class) (1)
public class ColorButtonConnector extends JmixButtonConnector {

    @Override
    public ColorButtonState getState() {
        return (ColorButtonState) super.getState(); (2)
    }

    @Override
    public void onStateChanged(StateChangeEvent event) { (3)
        super.onStateChanged(event);

        if (event.hasPropertyChanged("color")) { (4)
            Style style = getWidget().getElement().getStyle();
            style.setBackgroundColor(getState().color);
            style.setBackgroundImage("none");
        }
    }
}
1 使用此注解标记 ColorButtonConnector 连接器为具有服务器端对应实现。注解的值是 ColorButton - 服务器端实现的类。
2 返回此连接器的 ColorButtonState 对象。
3 对服务器状态变化做出响应。
4 如果服务器上的值已更改,则刷新小部件的样式。

使用 ColorButton

为了演示组件的工作原理,让我们创建一个新的 color-button-screen 界面。

打开 ColorButtonScreen.java 界面控制器并添加代码将组件放置于界面:

ColorButtonScreen.java
@UiController("sample_ColorButtonScreen")
@UiDescriptor("color-button-screen.xml")
public class ColorButtonScreen extends Screen {
    @Subscribe
    protected void onInit(InitEvent event) {
        ColorButton button = new ColorButton(); (1)
        button.setCaption("Button");
        button.setColor("#AFEEEE");
        getWindow().unwrap(Layout.class).addComponent(button); (2)
    }
}
1 初始化一个 ColorButton 组件实例。
2 使用 unwrap() 方法获取 Vaadin 容器的连接,并将新组件添加到其中。

下图为项目结构:

project structure

启动应用程序并查看结果:

color button