洗衣机UI

展示如何创建可以在桌面和MCU上运行的UI。

"Start screen"

洗衣机UI是洗衣机的控制面板应用程序。应用程序包含以下屏幕

  • 开始显示启动按钮
  • 预设显示最近使用的洗涤程序
  • 快速开始允许用户指定设置或启动选定的洗涤程序
  • 洗涤程序显示洗涤程序的设置
  • 运行中显示洗涤程序的进度

用户通过选择按钮在屏幕之间导航。我们使用连接来确定用户选择特定按钮时打开哪个屏幕,并使用状态来显示屏幕。我们使用时间线为按钮和运行中屏幕创建进度指示器。

此外,所有屏幕都包含一个显示当前时间的时钟组件。我们实现了一个TimeDate JavaScript对象来支持在Qt for MCUs上实现该功能,当时该组件不支持Date组件。

为MCU创建应用程序

我们使用Qt for MCUs应用程序项目模板创建MCU应用程序,这些应用程序仅支持预设组件的一个子集。

要创建MCU项目

  1. 选择文件 > 新建项目
  2. 预设选项卡中,选择Qt for MCUs预设。
  3. 详细信息选项卡中
    • 选择项目文件的路径。您可以在之后移动项目文件夹。
    • 将屏幕尺寸设置为匹配设备屏幕,这同样也允许在桌面上进行预览。您可以在属性中稍后更改屏幕尺寸。
  4. 选择创建以创建项目。

这样,在组件属性中仅可见在MCU上支持的组件和属性,我们不会意外地将不受支持的组件添加到我们的UI中,或者为受支持的组件指定不受支持的属性。有关更多信息,请参阅创建项目

此外,向导模板创建了一个通用的CMakeLists.txt文件,我们可以用它来配置和构建我们的示例应用程序,以便在MCU上运行。

注意:这个示例经过测试,可以从1.6版Qt for MCUs开始运行。您无法在较旧版本上运行它。此外,在撰写本文时,Qt for MCUs仅支持Qt 5。

创建屏幕

对于这个示例,我们使用外部工具设计UI,然后按照《从设计工具导出》中的说明,使用Qt Bridge将我们的设计作为资源和组件导出并导入到Qt Design Studio中。在导出时,我们只选择了Qt for MCUs支持的组件用于我们的组件。对于按钮组件,我们主要使用ImageTextMouse Area组件。对于屏幕背景,我们使用Rectangle组件。

文本可能在不同平台上看起来不同,因为我们在桌面使用动态字体加载,而在MCU上字体被编译到应用程序源代码中。因此,在MCU上文本始终是Maven Pro,而在桌面计算机上,您需要安装Maven Pro才能使用。通常您会看到系统默认字体。

我们还创建了一个更复杂的组件,称为MultSegmentArc,我们用它来指示按钮被按下。

或者,您可以在Qt Design Studio中从头开始创建屏幕,方法是选择文件 > 新建文件 > Qt Quick文件。在设计屏幕时,您可以将可重用组件移动到单独的文件中。有关更多信息,请参阅使用组件

创建进度指示器

我们创建了一个可重用的MultSegmentArc组件,并将其用于我们的BigbuttonSmallbutton组件中,以指示按钮按下进度。当按钮被按下时,该组件会在按钮周围显示一个动画圆弧。在桌面计算机上,用户只需点击一次即可将动画运行到底,而在MCU上,用户需要按下按钮直到动画完成。

"Button progress indicator"

我们的组件由四个块组成,圆弧段将旋转到其中,以指示进度。为了构建它,我们使用Image组件,这些组件是以圆弧的四段图片为源的图片,以及Rectangle组件,这些组件遮罩了圆弧应该隐藏直到旋转就位的那部分。对于Smallbutton组件,我们用较小的圆弧段图片覆盖了图像,以便它完美地围绕小按钮放置。

"MultSegmentArc component"

我们动画旋转属性,使每个圆弧段依次旋转到下一个块。

我们使用此组件代替Arc组件,该组件在MCU上不受支持。

现在我们可以添加一个时间线动画,以便按钮被按下时,圆弧在按钮周围移动。在“时间线”视图中,我们选择按钮,将1000帧的时间线添加到组件的root。我们将为所有其他字段使用默认值。

"Timeline settings"

首先,我们在导航器中选择初始圆弧段{i},以在属性中显示其属性。在几何-2D > 旋转中,我们选择动作),然后选择插入关键帧以插入我们可以在时间线视图中进行动画处理的关键帧。

"Inserting keyframe for Rotation property"

要在时间轴上开始记录旋转动画,我们检查播放头是否在帧0处,然后选择自动关键帧(K))按钮(或按k键)。

首先,我们将在帧0处的旋转设置为-90度在属性 > 几何 - 2D > 旋转。接下来,我们将播放头移动到帧250,设置旋转为0。

当我们取消选择记录按钮以停止记录时间轴时,新的时间轴将出现在视图中。

"Rotation animation in Timeline view"

现在我们重复以上步骤,为其他弧线段添加关键帧,并使它们的旋转属性从帧0的-90度移动到帧500(arcSegment2)、750(arcSegment3)和1000(arcSegment4)。

当我们移动时间轴上的播放头时,我们可以在2D视图中看到旋转动画。

创建状态

在我们的UI中,我们使用连接和状态在屏幕之间切换。首先,我们在ApplicationFlow.qml中指定应用程序工作流程。当文件在2D视图中打开时,我们将定义应用程序屏幕的组件从组件拖放到导航器2D视图中:StartScreenSettingsScreenPresetsScreenRunningScreen

"startScreen component in different views"

由于我们将使用状态来逐个显示屏幕,根据用户的选择,我们可以将所有屏幕放置在根组件的右上角。

然后,我们打开状态视图来创建显示特定屏幕的startsettingspresetsrunning状态,方法是选择创建新状态

"States view"

在Qt for MCUs中,状态的工作方式与Qt Quick不同,因此我们有时使用when条件来确定要应用的状态,有时使用信号和JavaScript表达式来切换状态。

将按钮连接到状态变化

在定义每个屏幕的每个文件中,我们将信号连接到按钮组件,以便用户选择按钮时切换到特定状态。

一些信号是为鼠标区域组件预先定义的,一些是我们必须自己添加的。例如,让我们看看我们在StartScreen.ui.qml中使用的开始按钮。首先,我们使用代码视图创建startClicked信号

Item {
    id: start
    width: 480
    height: 272

    signal startClicked

然后,在导航器中选择开始按钮的鼠标区域,startMA。在连接视图的连接选项卡中,我们选择添加)按钮。我们将信号设置为clicked操作设置为调用函数项目设置为startClicked。接下来,我们选择按钮以关闭连接设置选项。

"Connections view"

然后,在ApplicationView.qml中,我们指定startClicked()信号更改应用程序状态为presets

Item {
    id: root
    state: "start"

    width: 480
    height: 272

    StartScreen {
        id: startScreen

        visible: true

        onStartClicked: {
            root.state = "presets"
        }

我们必须这样做,因为我们正在为MCU开发。我们必须使用when条件或直接通过代码设置状态,以覆盖when条件。否则,我们只需在操作字段中选择要切换到的状态即可。

我们在其他屏幕的按钮组件和信号之间创建类似连接,以执行将用户移动到其他屏幕的其他操作。

有关更多信息,请参见连接组件到信号

显示当前时间

Qt for MCUs 不支持 Date 组件,且 JavaScript Date() 对象的实现返回自应用程序启动以来的已过时间,而不是如 ECMAScript 规范中指定的当前日期和时间。

为了克服桌面上的这一限制,我们在 Timedate.qml 文件中创建了自己的组件,其中包含我们以后获取小时和分钟的当前时间所需的某些属性。

Item {
    id: timedate
    width: 47
    height: 29

    readonly property alias currentHourInt: timeContainer.hrsInt
    readonly property alias currentMinuteInt: timeContainer.minInt

在 MCU 上,我们不幸还要看到自应用程序启动以来的已过时间。然而,在 运行 屏幕上指示所选洗涤程序的进度是有用的。

我们使用 Text 组件创建一个带格式文本的标签

    Text {
        id: timelabel
        x: 2
        y: -1
        width: 43
        height: 16
        color: "#B8B8B8"
        font.pixelSize: 16
        horizontalAlignment: Text.AlignHCenter
        font.family: "Maven Pro"

        text: timeContainer.hrsStr + ":" + timeContainer.minStr
    }

我们将 Item 作为一个逻辑模块来获取和格式化当前时间信息

    Item {
        id: timeContainer
        property string hrsStr: "00"
        property string minStr: "00"

        property int hrsInt: 0
        property int minInt: 0

        Timer {
            id: timer
            interval: 1000
            running: true
            repeat: true

            onTriggered: {
                updateTime()
            }

我们使用 updateTime() 函数以小时和分钟显示当前时间

            function updateTime() {
                var currentDate = new Date()
                timeContainer.hrsInt = currentDate.getHours()
                if (timeContainer.hrsInt < 10) timeContainer.hrsStr = "0" + timeContainer.hrsInt
                else timeContainer.hrsStr = timeContainer.hrsInt

                timeContainer.minInt = currentDate.getMinutes()
                if (timeContainer.minInt < 10) timeContainer.minStr = "0" + timeContainer.minInt
                else timeContainer.minStr = timeContainer.minInt
            }

为了使用两位数字表示小时和分钟,我们使用 hrsStrminStrhrsIntminInt 属性为小于 10 的值添加额外的零。这样,时钟将显示为 08:00 而不是例如 8:0

文件

在某些 Qt 许可证下提供。
了解更多信息。