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

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

create screen 3

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

单击 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.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 - 导航至界面控制器。

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

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

工具窗口

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 面板。

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

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

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

component palette

组件层级树

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

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

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

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

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

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

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

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

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

component hierarchy

组件探查

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

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

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

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

component inspector

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

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

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

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

component inspector add button

源码检查

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 - 切换至对应的界面描述文件

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

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

  • Subscribe to Event - 可以订阅各种事件,下面有详细介绍

  • Install Delegate - 可以生成组件的委托,下面有详细介绍

依赖注入

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

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

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

controller injection

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

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

  • 界面 API 接口,

  • 基础设施接口,

  • 中间层服务,

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

  • 配置接口,

  • SLF4J Logger 实例。

事件处理

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

  • 点击顶部操作面板的 Subscribe to Event 操作,

  • 按下 Alt+Insert(Cmd+N)键,在弹出的 Generate 菜单中选择 Subscribe to Event

subscribe dialog

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

打开的窗口中提供以下事件:

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

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

  • 表示此界面的外部框架的生命周期的框架事件(Frame Events)。

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

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

委托

使用委托,可以为各种界面机制提供代码来代替其标准实现。例如,可以提供自己的函数来提交数据或选择表格行的图标。

委托是具有特定签名的控制器方法,并使用 @Install 进行注解。通过下列方式添加:

  • 点击顶部操作面板的 Install Delegate 操作,

  • 按下 Alt+Insert(Cmd+N)键,在弹出的 Generate 菜单中选择 Install Delegate:

install dialog

每个委托都在窗口右边提供了描述,该描述是从框架的 Javadocs 中提取的。

5.4.4. 使用应用程序菜单

菜单设计器允许定义应用程序主菜单并将其存储在 web-menu.xml 配置文件中。Structure 选项卡显示图形设计器,可以在 Text 选项卡上编辑菜单的 XML 代码。

web menu

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

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

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

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

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

菜单配置文件列表通过 cuba.menuConfig 应用程序属性定义,选择菜单模式时会更新此属性。

要添加菜单项,选择已有的菜单项(或配置文件以创建顶级菜单),然后单击 +。菜单项编辑窗口会在模式窗口中打开。

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

Screen - 界面

web menu create

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

应该为 Screen 项指定以下属性:

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

  • Id - 为菜单项指定任意唯一 ID。

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

  • Shortcut - 用于打开界面的快捷键。可选的组合键(ALT、CTRL、SHIFT)用“-”分隔,例如 ALT-C。

  • Style name - 定义菜单项的样式名称。有关详细信息,请参阅 主题

Menu - 菜单

web menu create 2

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

需要为 Menu 项指定以下属性:

  • Id - 为菜单项指定任意唯一 ID。

  • Style name - 定义菜单项的样式名称。

Bean

web menu create 3

调用 托管 Bean 方法的菜单项。

需要为 Bean 项指定以下属性:

  • Id - 为菜单项指定任意唯一 ID。

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

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

  • Shortcut - 用于方法调用的快捷键。可选的组合键(ALT、CTRL、SHIFT),用“-”分隔,例如 ALT-C。

  • Style name - 定义菜单项的样式名称。

Class - 类

web menu create 4

执行给定类的 run() 方法的菜单项。

需要为 Class 项指定以下属性:

  • Id - 为菜单项指定任意唯一 ID。

  • Class - 一个类的完全限定名,这个类需实现 Runnable 接口。

  • Shortcut - 用于方法调用的快捷键。可选的组合键(ALT 、CTRL 、SHIFT),用“-”分隔,例如 ALT-C。

  • Style name - 定义菜单项的样式名称。

Separator - 分隔符

分隔菜单项的水平线。

5.4.5. 使用主题

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

theme extension

创建主题扩展或自定义主题时,会创建特定目录结构并修改 build.gradle 文件。

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

halo ext

扩展或创建主题后,可以在 SCSS 文件或可视化编辑器中手动修改其变量: 在新主题的右键菜单中,选择 Open Variables File。此文件也可以通过 CUBA 主菜单:选择 Advanced > Manage themes > Edit theme variables

theme variables