5.4. 通用 UI

Studio 提供了许多有助于在应用程序中使用 通用 UI 的功能。

在项目树中,可以看到 Generic UI 的以下元素:

  • Web Menu 打开主菜单的图形编辑界面。

  • Main Message Pack 部分包含主菜单项和通用 UI 元素的消息。

  • Screens 部分显示已有的应用程序界面。

  • Themes 用于管理应用程序的可视化展现。

5.4.1. 创建和移除界面

要创建新的 Generic UI 界面,请在项目树中选择 Generic UI,然后在右键菜单中选择 New > Screen。如果要为实体创建 CRUD 界面,请在项目树中选择此实体,然后在右键菜单中点击 New > Screen

create screen

Studio 将显示可用模板的列表。该列表分为两部分:Screen TemplatesLegacy Screen Templates。 前者包含框架版本 7 以上可用于新界面 API 的模板,而后者包含也可用于版本 6 的界面模板。

create screen 2

如果为在项目树中选中的实体创建界面,则 Entity 字段会自动填充:

create screen 3

Advanced 部分允许修改自动生成的界面描述和控制器名称以及界面 ID。当某个实体有多个界面时,这很有用。

Entity browser viewEntity editor view 的向导步骤中,可以选择需要展示在数据表格或者编辑界面表单中的数据。这些选中的属性也会作为 实体视图 用来加载实体至界面:

create screen view step

点击 Finish 之后,会自动创建界面 XML 描述,Java 控制器以及消息包文件,并在源码编辑器打开。对于不使用 UiDescriptor@UiController 注解的遗留界面,界面描述文件会在 web-screens.xml 文件中注册。

移除界面

移除界面文件时,使用 Safe delete 选项查找并清理对这个界面的引用:

safe delete screen 1

如果 web-menu.xmlweb-screens.xml 文件中也存在删除界面的引用,则这些引用会被自动删除。如果还有其他引用,则会显示关于这些引用还在使用的警告。点击对话框中的 View Usages,查看 Find 工具窗口中的这些引用,根据需要选择 CancelDo Refactor

safe delete screen 2

5.4.1.1. 自定义界面模板

Studio 支持自定义界面模板,可以从标准界面模板复制到项目,然后做自定义修改,比如修改界面描述的模板文件,界面控制器甚至在界面向导中添加新的参数。

选择需要自定义的模板,然后在 Create CUBA Screen 向导的第一步点击 Copy template 按钮,即可创建自己的界面模板。输入自定义模板的代码名称。模板文件会复制到项目,可以手动修改。自定义的界面模板展示在 CUBA 项目树的 Generic UIScreensCustom Templates 部分。

custom screen templates tree

可以修改界面控制器和描述的模板文件,通过扩展 settings.xml 文件甚至可以为向导添加新的参数。

NewScreen 向导的第一步中,Project Templates 标签页可以选择自定义的界面模板:

screen wizard custom template

自定义模板示例

示例如下,需要根据向导中输入的参数调整实体浏览界面的宽高:

  1. 编辑 settings.xml 添加如下标签:

    1. <property caption="Dialog Width" code="dialogWidth" propertyType="INTEGER" defaultValue="800" preferences="true"/>
    2. <property caption="Dialog Height" code="dialogHeight" propertyType="INTEGER" defaultValue="600" preferences="true"/>
  2. 编辑 descriptor.xml,修改 dialogMode 标签声明如下:

    1. <dialogMode height="${dialogHeight}"
    2. width="${dialogWidth}"/>
  3. 如果在界面向导中使用新修改的模板,则能看到向导中新添加的参数:

    custom screen template parameter

5.4.2. 使用界面描述

界面 XML 描述 编辑器与 Screen Designer 集成在一起。界面设计器展示一组操作面板和工具窗口,可以用来开发界面的布局并以所见即所得的形势设置 UI 组件的属性。您可以直接编辑 XML 或使用设计器的面板生成代码。

Screen Designer 由下列元素组成:

  • Source code editor - 展示并编辑 XML 源码。

  • Top actions panel - 提供一些便于访问的操作。

  • Layout preview panel - 展示交互式的界面布局架构。

  • Component Hierarchy - 以层级树的形势展示界面元素。

  • Component Palette - 展示可以添加到当前界面的组件。

  • Component Inspector - 展示并编辑组件的属性和事件处理器。

Tip

界面设计器面板和工具窗口只有购买了 CUBA Studio 商业订阅才能使用。

screen designer

顶部操作面板

操作面板位于代码编辑器的顶部。提供下列操作的访问:

  • Controller - 导航至界面控制器。

  • <entity class name> - 如果当前界面是实体浏览器或者编辑器时会显示。可以导航至关联的实体。

也可以用侧边栏的标记在界面描述和其控制器之间切换。

工具窗口

Component HierarchyComponent PaletteComponent Inspector 面板是 IDE 中独立的工具面板。当在编辑器打开界面描述时,会自动打开这些工具窗口。如果在编辑器中切换界面描述文件,工具窗口的内容也会同步更新。有时候,当打开其他工具窗口时(比如 Gradle、Persistence 等),设计器的某些窗口会被隐藏,可以通过点击 IDE 窗口左右的相应按钮重新打开。

保留在左下角展示 Component Inspector 是为了满足熟悉之前布局的开发者们。如果需要将该面板移至右侧,点击面板标题的 Move to Right Bottom 即可。

设计器面板会在编辑 XML 代码时激活。熟练开发者们通过编辑 XML 源码切换和修改界面描述,他们现在也能获得界面设计器的编辑功能帮助。可以从工具箱拖拽新组件至层级树,当编辑器只显示源码时,也可以在左下角的探查面板修改组件的排序和编辑组件属性。源码会直接同步所有改动。

布局预览面板

Layout Preview - 布局预览面板 展示交互式的界面布局架构。与界面描述的源码编辑面板共享编辑器的空间。现在在界面描述的右上部添加了四个按钮用于切换界面预览模式:

  • Editor only - 在编辑器只显示源码。

  • Editor and Preview - 编辑器空间分割,包含源码和预览。

  • Preview only - 只显示预览。

  • Preview in Window - 源码在编辑器展示,但是预览通过单独的窗口展示,可以将预览窗口移至其他显示设备。

layout preview modes

面板在右上角有一些控制按钮:

layout preview controls

  • 100% x 100% 下拉框可以选择固定的 画布大小。画布的大小可以比预览面板大,此时会添加额外的滚动条。例如,如果在开发一个复杂的界面,带有很多控制组件,如果想预览,可以选择 1920 x 1080 画布大小,然后查看布局在大屏上如何展示。

  • Refresh 按钮重新加载预览界面的内容。

  • Zoom InZoom OutZoom Reset 按钮更改预览界面的缩放。

  • 最右边的按钮展示自动界面布局问题检测的结果。移动光标至这个图标可以看到发现的问题。

Layout Preview 面板中,也可以排布组件以达到需求的布局。组件可以用控制进行缩放和对齐:

  • 水平延展,

  • 垂直延展,

  • 水平、垂直对齐组件。

layout component controls

组件工具箱

Component Palette 工具窗口展示在 IDE 的右下角。显示可用的界面组件:

  • Containers - 容器;

  • Components - 组件;

  • Data Components - 数据组件:containers - 数据容器 和 loaders - 数据加载器;

  • Non-visual - 非可视化组件:actions - 操作、 dialog mode settings - 对话框模式设置,timers - 定时器以及其他辅助的界面元素;

  • Main window - 主窗口: 主界面特定的组件。

可以通过在搜索框输入名称的方式在工具箱搜素组件。

要在布局中添加一个组件,可以直接从工具箱拖拽组件至: * Component Hierarchy 面板。 * 或者 XML 代码中合适的位置。

在工具箱右键点击组件,可以使用下列操作:

  • Add to Design - 添加选中的组件至界面,放置位置通过在层级树中选中元素决定。

  • CUBA Documentation - 打开组件在开发者手册中的文档页。

component palette

组件层级树

Component Hierarchy 工具窗口展示在 IDE 的右上角。以树的方式展示布局中的组件结构。

可用拖拽的方式修改树中元素的位置。

右键点击层级树中的元素,可以使用下列操作:

  • Convert 将组件转换为类似的其他组件。

  • Wrap 将组件放入建议的容器中。

  • Go to XML - 切换至源码中相应的 XML 标签。

  • Inject 将元素注入界面控制器或者导航至已经注入的声明。

  • DeleteCopyCut Paste 删除、复制、剪切、粘贴组件。

  • CUBA Documentation 打开选中组件的文档。

component hierarchy

组件 Inspector

Component Inspector 工具窗口显示在 IDE 的左下角。展示并编辑选中组件的属性:

  • Properties 面板展示可视化组件的属性。

  • Handlers 面板展示可以与选中组件关联的事件监听器和组件委托。如要生成所需的处理器方法,只需双击相应的条目。

可以在搜索字段中输入文字快速定位属性:

component inspector

对于某些选中的元素会显示 + Add 按钮,提供添加子元素的一个快捷方法,比如添加表格操作、列、表单字段。如果所选组件是:

  • TableGrid 或其操作和列之一 - 可用:AddColumn, AddGroup, AddAction

  • Form 或其列和字段之一 - 可用:AddColumn, AddField

  • DataLoadCoordinator - 可用:AddonScreenEvent trigger 以及其它触发器

component inspector add button

支持自定义 UI 组件

界面设计器可以集成在扩展插件或者项目中的自定义 UI 组件,这些组件需要使用特定的注解。集成之后,可以在 Component Palette - 组件工具箱 展示自定义组件,其属性也可以在 Component Inspector 面板编辑。自定义 UI 组件的支持需要 CUBA 平台版本 7.1.77.2.5 以上。

参阅 开发者手册 中相关内容了解关于自定义 UI 组件元数据的更多内容。

源码检查

Studio 会检查界面布局是否存在错误和不一致,并且检查内部和外部引用。出现下列情况,会用警告或高亮显示 XML 元素的方式进行提醒:

  • 由于 XML 错误,无法组装界面布局。

  • 组件属性路径和名称与应用程序数据模型不对应。

  • 组件大小冲突: widthheightexpand 属性值的冲突。

  • dataContainerdataLoader 属性没有引用任何现有的数据容器或数据加载器。

  • form 中的字段没有显式定义 property XML 属性:此时,id 将被隐式地用作 property

  • form 元素语义错误:字段重复或位于 column 元素之外。

  • gridLayout 中的列数与指定的数字不匹配。

  • 在扩展界面中出现重复的元素属性,比如父界面和扩展界面中同时定义了完全一样的属性时。

  • 扩展界面中的元素的命名与父界面中不同,或者放置位置不正确。

  • messagesPack 属性指定的值不是一个有效的包,这个包要至少包含一个 messages_xx.properties 文件。

  • 过时的 XSD 引用。

  • id 值在界面内不是唯一的。

  • 其它问题。

可以在 Settings 窗口中配置 CUBA 检查器(CUBA > Settings > Editor > Inspections)。

源码意图和生成菜单

意图操作(Intention action)是一个上下文敏感的操作,开发者可以在源码编辑器通过按下 Alt+Enter(Option+Enter)调用。意图操作可以帮助代码重构、代码生成、导航和其他任务。可以在 https://www.jetbrains.com/help/idea/intention-actions.html 阅读更多关于意图操作的内容。

Generate - 自动生成 菜单包含上下文敏感的操作,可以帮助生成各种代码结构。可以通过按下 Alt+Insert(Cmd+N)调出。参阅 https://www.jetbrains.com/help/idea/generating-code.html 了解更多。

Studio 中包含的意图和生成菜单条目提高了使用界面组件的效率。使用 Alt+Insert(Cmd+N)和 Alt+Enter(Option+Enter)查看对于特定 UI 和数据组件的功能。

  1. 例如,要为 表单 组件添加一个新字段,可以将光标移入 form 元素然后执行下列操作的一项:

    • 按下 Alt+Insert (Cmd+N),选择 Add field,然后选择 property 属性的值,

      gui Form add

    • 输入 field 然后按下 TAB 键,然后选择 property 属性的值。

      gui Form add tab

  2. 另一个例子是为一个组件添加新的本地化语言标题。可以在源码中输入还未创建的消息键值。则引用的元素会高亮红色。然后按下 Alt+Enter(Option+Enter)并选择 Create message in the message bundle

    intention add localized message

5.4.3. 使用界面控制器

本节介绍 Studio 为 界面控制器 提供的功能。

利用源码编辑器的边栏图标可以快速切换到相应的 XML 描述文件、定位到注入组件的 XML 定义以及其它导航功能。

controller

顶部操作面板

操作面板位于控制器代码编辑器的顶部。展示下列操作:

  • Descriptor - 切换至对应的界面描述文件

  • <entity class name> - 切换至当前浏览界面或者编辑界面关联的实体。

  • Main Menu - 可以将当前界面加入主菜单或者切换至主菜单配置

  • Inject - 帮助在控制器类中注入依赖,下面有详细介绍

  • Generate Handler - 可以订阅各种事件以及生成组件的代理,下面有详细介绍。

依赖注入

依赖注入是在界面控制器代码中获取对可视化组件和 API 端点(api endpoint)的引用的主要方式。当然,也可以编写所需类型的字段并手动进行注解。但是 Studio 提供了一个专用的窗口,这个窗口允许从列表中选择一个对象并自动创建合适的字段。窗口可以通过下列方式打开:

  • 点击顶部操作面板的 Inject 操作,

  • 按下 Alt+Insert(Cmd+N)键,在弹出的 Generate 菜单中选择 Inject…​

controller injection

以下对象可以被注入到控制器中:

  • 界面 XML 描述中定义的可视化组件和数据组件,

  • 界面 API 接口,

  • 基础设施接口,

  • 中间层服务,

  • 项目中定义的其他 Spring bean,

  • 配置接口,

  • SLF4J Logger 实例。

事件处理器和代理方法

有两种方式可以在界面控制器添加界面生命周期相关的逻辑和组件行为方法:事件处理器以及组件代理。这两种方式在框架中实现不同,但在 Studio 中用法类似。

使用事件处理器,可以在界面生命周期的各个点执行代码并对用户操作做出响应。处理器是一个用 @Subscribe 注解的控制器方法,使用事件作为输入参数。

使用代理,可以提供代码替换界面中各种机制的标准实现。比如,您可以提供自己的函数用来提交数据或者为表格行选择图标。代理是一个特定签名的控制器方法,并且使用 @Install 注解。

可以在 Studio 中创建事件处理器和代理方法:

  • 点击顶部操作面板的 Generate Handler

  • 或者按下 Alt+Insert(Cmd+N)键,在弹出的 Generate 菜单中选择 Generate Handler

generate handler dialog

每个事件或代理在窗口右侧都提供了描述,这个描述是从事件的 Javadoc 中提取的。

打开的窗口中提供以下事件和代理方法:

  • 表示界面生命周期的控制器事件。

  • 可对按钮点击、表格选择、操作等做出响应的组件事件。

  • 表示此界面的外部框架的生命周期事件处理器。

  • 允许对数据上下文更改做出响应,并在数据提交前后执行代码的数据上下文事件。

  • 允许接收有关数据容器和实体状态更改通知的数据容器事件。

  • 可实现为界面组件自定义加载数据逻辑的数据加载器事件处理器。

5.4.4. 使用应用程序菜单

应用程序菜单配置保存在 web-menu.xml 配置文件中,该文件位于项目的 web 模块。如需修改主菜单配置,可以使用 CUBA 项目树的 Generic UIMain Menu

main menu in tree

菜单设计器允许可视化定义应用程序主菜单结构。Structure 选项卡显示图形设计器,可以在 Text 选项卡上编辑菜单的 XML 代码。

web menu

Tip

菜单设计器只有激活 CUBA Studio 订阅才能使用。

主菜单模式

菜单可以以两种模式创建:

  • Single mode 中,菜单仅包含当前项目的 web-menu.xml 文件中的菜单项。在这种情况下,需要创建所有菜单项,必要时还需要将应用程序组件中的菜单项也定义进来,这种方式有点麻烦,但好处是可以完全控制菜单结构。

  • Composite mode 中,菜单除了包含当前项目的 web-menu.xml 中的菜单项,还包含所有应用程序组件的菜单配置文件中的菜单项。这种模式可以很方便地包含所有继承的菜单项,可以在菜单结构的任何位置插入当前项目需要的菜单项。继承的菜单项不能被修改。

    此外,在 Text 选项卡上,可以为菜单项定义 insertBeforeinsertAfter 属性。这两个属性定义了当前菜单项的插入位置。在 Composite 模式下,这两个属性有助于将当前项目菜单项与继承的应用程序组件菜单项组合在一起。

    例如,如果要将当前项目的菜单结构放在 Administration 菜单项的左侧,可以为当前项目的菜单树的根菜单项设置属性 insertBefore="administration"

    在可视化设计器中,可以在菜单树中拖拽菜单项改变它们在菜单结构中的位置。

菜单配置文件列表通过 cuba.menuConfig 应用程序属性定义,选择菜单模式时会更新此属性。 当菜单模式从 Composite 切换至 Single 模式,Studio 建议您保留从平台和扩展插件继承的菜单项:

menu switch mode single

如果您决定保留继承的菜单项,这些菜单项的结构会复制到您的项目然后就可以自定义这些菜单了(比如,添加图标,修改菜单标题等)。

如果在后来某个时候,您决定将主菜单切换回 Composite 模式,注意,此时您需要手动从项目的菜单配置中移除哪些重复的菜单和菜单项。否则,菜单会没法显示,因为不允许有重复的菜单项。

添加菜单项

如需添加菜单项,选择菜单中已经存在的一项(或选择配置文件以添加顶级菜单)然后点击 + 。会以模态窗形式打开菜单项编辑界面窗口。

新的菜单项创建之后,可以在菜单树中拖拽修改它在菜单结构中的位置。

可以创建以下类型的菜单项:

Screen - 界面

web menu create

用于打开应用程序界面的菜单项。

Screen 菜单项可以设置下列属性:

  • Screen - 这个菜单项打开的界面的非唯一 ID。

  • Open type - 定义界面打开的方式,可以在新的选项卡打开,或者以模态窗的方式打开(NEW_TABDIALOG)。默认使用 NEW_TAB

Menu - 菜单

包含其它菜单项(子菜单)的菜单项。

web menu create 2

Spring bean

执行 Spring bean 方法的菜单项。Bean 需要存在于 web 模块。

Bean 菜单项可以设置下列属性:

  • Bean - 可以通过 AppBeans 获取到的 bean 的名称(例如 cuba_Messages)。

  • Bean method - 要调用的 bean 的方法名称。

web menu create 3

Class - 类

web menu create 4

指定给定类的一个方法的菜单项。

Class 菜单项可以设置下列属性:

  • Class - 类的全路径名称,此类需要实现下列接口之一:

    • java.lang.Runnable

    • java.util.function.Consumer<Map<String, Object>>

    • com.haulmont.cuba.gui.config.MenuItemRunnable

Separator - 分隔符

分隔菜单项的水平线

通用参数

下列参数对各种菜单项都适用:

  • Menu item - 父菜单或父菜单项,当前菜单放在这个菜单(项)内。

  • Id - 此菜单项的唯一 ID。该属性不是必须的,但是如果需要 动态管理菜单配置 则推荐设置。

  • Caption - 菜单显示的本地化名称。点击地球仪按钮可以打开 Localized Message 对话框,能输入所有支持语言的本地化消息。

  • Shortcut - 触发该菜单项的快捷键。功能键(ALT,CTRL,SHIFT)通过 “-“ 分隔,比如,“ALT-C”。

  • Style name - 为菜单项设置样式名称。参阅 Themes 了解细节。

创建了菜单项之后,在设计器选中菜单项之后,右侧面板可以编辑下面的参数:

  • Icon - 菜单图标

  • Description - 鼠标浮于菜单时显示的 tooltip 提示。点击地球仪按钮可以打开 Localized Message 对话框,能输入所有支持语言的本地化消息。

  • Params - 界面参数,传递给被打开界面控制器的 init() 方法。

  • Permissions - 可以限制对该菜单的访问。如果用户没有权限访问该菜单项,则不会显示在菜单中。有个更简单访问控制管理办法,就是使用角色的界面权限。

请继续阅读 开发者手册 的相关内容了解这些参数的更详细解释。

5.4.5. 使用主题

Studio 可以帮助在项目中创建 主题 扩展和自定义主题。

theme extension

创建主题扩展或自定义主题时,会在 app-web 模块的 themes 子目录创建特殊的主题目录结构并在 build.gradle 文件添加新的 Gradle 任务支持主题构建。

创建的主题会显示在项目树的 Themes 部分中。

theme files in tree

扩展或创建主题后,可以在 SCSS 文件或可视化编辑器中手动修改其变量: * 在新主题的右键菜单中,选择 Open Variables File。 * 通过 CUBA 主菜单:选择 CUBAAdvancedManage themesEdit %ThemeName% Theme Variables

theme variables

Tip

主题变量的可视化编辑器只有激活 CUBA Studio 订阅之后才能使用。