Qt Quick 演示 - 时钟

一个 QML 时钟应用程序,演示了如何使用ListView 类型显示由ListModel 生成的数据,以及如何使用SpringAnimation 类型制作图像动画。

时钟演示了如何使用ListView 类型显示由ListModel 生成的数据。模型使用的委托被指定为 Clock.qml 文件中指定的自定义 QML 类型。

JavaScript 方法用于获取不同时区多个城市的当前时间,而 QML 类型则用于在带有动画指针的钟面上显示时间。

运行示例

要从 Qt Creator,打开Welcome 模式,并从Examples 中选择示例。更多信息,请参阅Qt Creator: Tutorial:构建并运行

显示由列表模型生成的数据

在 Main.qml 文件中,我们使用Rectangle 类型创建应用程序主窗口:

Rectangle {
    id: root
    width: 640; height: 320
    color: "#646464"

我们使用ListView 类型显示由ListModel 类型提供的项目列表:

    ListView {
        id: clockview
        anchors.fill: parent
        orientation: ListView.Horizontal
        cacheBuffer: 2000
        snapMode: ListView.SnapOneItem
        highlightRangeMode: ListView.ApplyRange

        delegate: Clock {
            required city
            required shift
        }
        model: ListModel {
            ListElement { city: "New York"; shift: -4 }
            ListElement { city: "London"; shift: 0 }
            ListElement { city: "Oslo"; shift: 1 }
            ListElement { city: "Mumbai"; shift: 5.5 }
            ListElement { city: "Tokyo"; shift: 9 }
            ListElement { city: "Brisbane"; shift: 10 }
            ListElement { city: "Los Angeles"; shift: -8 }
        }
    }

列表元素的定义与其他 QML 类型相似,只是它们包含角色定义集合,而不是属性。角色既定义数据的访问方式,也包括数据本身。

对于每个列表元素,我们使用cityName 角色指定一个城市的名称,使用timeShift 角色指定一个时区,作为从 UTC(协调世界时)的正或负偏移。

时钟自定义类型用作ListViewdelegate ,定义列表项的视觉外观。

我们使用图像类型来显示箭头,以指示用户是否可以滑动视图以查看左侧或右侧的更多时钟:

    Image {
        anchors.left: parent.left
        anchors.bottom: parent.bottom
        anchors.margins: 10
        source: "images/arrow.png"
        rotation: -90
        opacity: clockview.atXBeginning ? 0 : 0.5
        Behavior on opacity { NumberAnimation { duration: 500 } }
    }

    Image {
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        anchors.margins: 10
        source: "images/arrow.png"
        rotation: 90
        opacity: clockview.atXEnd ? 0 : 0.5
        Behavior on opacity { NumberAnimation { duration: 500 } }
    }
}

当列表视图位于 x 轴的起点或终点时,我们使用opacity 属性隐藏箭头。

在 Clock.qml 中,我们定义了一个timeChanged() 函数,在该函数中,我们使用 JavaScriptDate 对象中的方法来获取当前的 UTC 时间,并将其调整为正确的时区:

    function timeChanged() {
        var date = new Date;
        hours = internationalTime ? date.getUTCHours() + Math.floor(clock.shift) : date.getHours()
        night = ( hours < 7 || hours > 19 )
        minutes = internationalTime ? date.getUTCMinutes() + ((clock.shift % 1) * 60) : date.getMinutes()
        seconds = date.getUTCSeconds();
    }

我们使用Timer 类型以 100 毫秒为间隔更新时间:

    Timer {
        interval: 100; running: true; repeat: true;
        onTriggered: clock.timeChanged()
    }

我们使用Item 类型中的图像类型在模拟钟面上显示时间。白天和夜间使用不同的图像:

    Item {
        anchors.centerIn: parent
        width: 200; height: 240

        Image { id: background; source: "images/clock.png"; visible: clock.night == false }
        Image { source: "images/clock-night.png"; visible: clock.night == true }

应用于图像类型的Rotation 变换提供了一种旋转时钟指针的方法。origin 属性保留了在项目其余部分旋转时相对于父项固定的点。angle 属性决定了顺时针旋转指针的角度。

        Image {
            x: 92.5; y: 27
            source: "images/hour.png"
            transform: Rotation {
                id: hourRotation
                origin.x: 7.5; origin.y: 73;
                angle: (clock.hours * 30) + (clock.minutes * 0.5)
                Behavior on angle {
                    SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
                }
            }
        }

        Image {
            x: 93.5; y: 17
            source: "images/minute.png"
            transform: Rotation {
                id: minuteRotation
                origin.x: 6.5; origin.y: 83;
                angle: clock.minutes * 6
                Behavior on angle {
                    SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
                }
            }
        }

        Image {
            x: 97.5; y: 20
            source: "images/second.png"
            transform: Rotation {
                id: secondRotation
                origin.x: 2.5; origin.y: 80;
                angle: clock.seconds * 6
                Behavior on angle {
                    SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
                }
            }
        }

        Image {
            anchors.centerIn: background; source: "images/center.png"
        }

我们在angle 属性上使用Behavior 类型,以便在时间发生变化时应用SpringAnimationspringdamping 属性可使时钟指针像弹簧一样运动,而modulus360 属性可使动画目标值绕一整圈。

我们使用Text 类型在时钟下方显示城市名称:

        Text {
            id: cityLabel
            y: 210; anchors.horizontalCenter: parent.horizontalCenter
            color: "white"
            font.family: "Helvetica"
            font.bold: true; font.pixelSize: 16
            style: Text.Raised; styleColor: "black"
            text: clock.city
        }

示例项目 @ code.qt.io

另请参阅 QML 应用程序

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.