QML输入控件:Tumbler应用案例(2)

目录

引言

应用案例

示例1:日期选择器

示例2:颜色选择器

示例3:设置选择器

完善示例1:日期选择器Pro版

代码要点

与示例1的实现差异

运行效果

结语


引言

接上篇,本文侧重介绍Tumbler控件的实际应用场景。接下来会介绍几个案例,分别是:日期选择器、颜色选择器、设置选择器。

相关阅读:

Tumbler QML Type | Qt Quick Controls 6.8.3

QML输入控件:Tumbler 基础用法与样式(1)-优快云博客

实现效果展示:


应用案例

示例1:日期选择器

import QtQuick
import QtQuick.Controls

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("日期选择器")

    Row {
        spacing: 5
        anchors.centerIn: parent

        Tumbler {
            id: monthTumbler
            width: 100
            model: ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
                    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
        }

        Tumbler {
            id: dayTumbler
            width: 70
            model: 31
        }

        Tumbler {
            id: yearTumbler
            width: 90
            model: ListModel {
                Component.onCompleted: {
                    for (var i = 2020; i <= 2030; ++i)
                        append({value: i.toString()})
                }
            }
            delegate: Text {
                text: value
                horizontalAlignment: Text.AlignHCenter
            }
        }
    }
}

这段代码展示了一个日期选择器的实现。它使用了三个 Tumbler 控件,分别用于选择月份、日期和年份。

运行效果:

窗口中有一个日期选择器,包含三个滚轮选择器:

  • 第一个滚轮显示月份("Jan" 到 "Dec")。
  • 第二个滚轮显示日期(1 到 31)。
  • 第三个滚轮显示年份(2020 到 2030)。

用户可以通过滚动滚轮来选择具体的日期。

 

示例2:颜色选择器

import QtQuick
import QtQuick.Controls

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("颜色选择器")

    Tumbler {
        anchors.centerIn: parent
        model: ["Red", "Green", "Blue", "Yellow", "Cyan", "Magenta"]

        delegate: Rectangle {
            width: Tumbler.tumbler.width
            height: 30
            color: modelData
            border.color: "white"
            border.width: 1

            Text {
                text: modelData
                anchors.centerIn: parent
                color: "white"
                font.bold: true
            }
        }
    }
}

这段代码展示了一个简单的颜色选择器的实现。用户可以通过滚动选择不同的颜色。

运行效果:

运行后,窗口中有一个颜色选择器,用户可以通过滚动滚轮来选择不同的颜色。每个选项显示为一个矩形,矩形的颜色与选项名称对应,并在矩形中显示颜色名称(白色加粗)。

 


示例3:设置选择器

import QtQuick
import QtQuick.Controls

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("设置选择器")

    Column {
        anchors.centerIn: parent

        Text {
            text: "Volume"
            font.bold: true
            anchors.horizontalCenter: parent.horizontalCenter
        }

        Tumbler {
            id: volumeTumbler
            model: 11
            currentIndex: 5
            delegate: Text {
                text: index * 10
                horizontalAlignment: Text.AlignHCenter
                font.pixelSize: 14
                opacity: 0.4 + (1 - Math.abs(Tumbler.displacement)) * 0.6
            }
        }

        Text {
            text: "Current: " + (volumeTumbler.currentIndex * 10)
            anchors.horizontalCenter: parent.horizontalCenter
        }
    }
}

这段代码展示了一个简单的“设置选择器”界面,用于调整音量。它使用了一个 Tumbler 控件来实现音量的滚动选择,并通过文本显示当前音量值。

运行效果:

运行后,窗口中有一个用Tumbler 控件实现的音量选择器,用户可以通过滚动选择音量(0 到 100,步长为 10)。在窗口底部显示当前选中的音量值(例如“Current: 50”)。

 


完善示例1:日期选择器Pro版

以下实现方案展示了一个专业的日期选择器应该具备的核心功能,同时也展示了 QML 中组件、属性绑定和信号处理的典型用法。

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("日期选择器Pro")
    color: "#404040"

    property int currentYear: new Date().getFullYear()
    property int currentMonth: new Date().getMonth() + 1
    property int currentDay: new Date().getDate()

    // 获取指定年月的天数
    function getDaysInMonth(year, month) {
        return new Date(year, month, 0).getDate()
    }

    Rectangle {
        anchors.centerIn: parent
        width: row.width + 40
        height: row.height + 40
        color: "#202020"
        radius: 10

        RowLayout {
            id: row
            anchors.centerIn: parent
            spacing: 20

            // 年份选择器
            Tumbler {
                id: yearTumbler
                Layout.preferredWidth: 120
                Layout.preferredHeight: 300
                model: ListModel {
                    id: yearModel
                }
                visibleItemCount: 5
                delegate: Text {
                    text: modelData
                    color: "white"
                    font.pixelSize: 16 + (1 - Math.abs(Tumbler.displacement)) * 8
                    opacity: 0.5 + (1 - Math.abs(Tumbler.displacement)) * 0.5
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                    width: 120
                }
            }

            // 月份选择器
            Tumbler {
                id: monthTumbler
                Layout.preferredWidth: 80
                Layout.preferredHeight: 300
                model: 12
                visibleItemCount: 5
                delegate: Text {
                    text: (modelData + 1) + "月"
                    color: "white"
                    font.pixelSize: 16 + (1 - Math.abs(Tumbler.displacement)) * 8
                    opacity: 0.5 + (1 - Math.abs(Tumbler.displacement)) * 0.5
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                    width: 80
                }
            }

            // 日期选择器
            Tumbler {
                id: dayTumbler
                Layout.preferredWidth: 80
                Layout.preferredHeight: 300
                model: ListModel {
                    id: dayModel
                }
                visibleItemCount: 5
                delegate: Text {
                    text: modelData + "日"
                    color: "white"
                    font.pixelSize: 16 + (1 - Math.abs(Tumbler.displacement)) * 8
                    opacity: 0.5 + (1 - Math.abs(Tumbler.displacement)) * 0.5
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                    width: 80
                }
            }
        }
    }

    // 更新年份模型
    function updateYearModel() {
        var years = []
        for (var i = currentYear - 50; i <= currentYear + 50; ++i) {
            years.push(i)
        }
        yearTumbler.model = years
        yearTumbler.currentIndex = 50  // 设置当前年份位置
    }

    // 更新日期模型
    function updateDayModel() {
        var year = yearTumbler.model[yearTumbler.currentIndex]
        var month = monthTumbler.currentIndex + 1
        var days = getDaysInMonth(year, month)
        
        var daysArray = []
        for (var i = 1; i <= days; ++i) {
            daysArray.push(i)
        }
        dayTumbler.model = daysArray
        
        // 确保当前选中的日期有效
        if (dayTumbler.currentIndex >= days) {
            dayTumbler.currentIndex = days - 1
        }
    }

    // 监听年月变化,更新日期
    Connections {
        target: yearTumbler
        function onCurrentIndexChanged() { updateDayModel() }
    }
    
    Connections {
        target: monthTumbler
        function onCurrentIndexChanged() { updateDayModel() }
    }

    Component.onCompleted: {
        updateYearModel()
        monthTumbler.currentIndex = currentMonth - 1
        updateDayModel()
        dayTumbler.currentIndex = currentDay - 1
    }
}

代码要点

选择器实现(以年份选择器为例): 

  • visibleItemCount: 5 控制可见项数量
  • 使用 Tumbler.displacement 实现字体大小和透明度的动态变化
  • delegate 定义了每个项的显示样式

日期计算核心函数:

  • getDaysInMonth 利用 JavaScript Date 对象计算月份天数
  • updateYearModel 生成前后各50年的年份范围
  • updateDayModel 根据年月动态更新日期,并处理日期合法性
  • 使用 Connections 监听年月变化,自动更新日期选项

与示例1的实现差异

Pro版本具有:

  • 更精美的视觉效果,包括文字大小渐变和透明度变化
  • 动态日期计算(根据年月自动调整天数)
  • 年份范围更大(当前年份±50年)
  • 自动定位到当前日期
  • 确保日期选择的合法性

示例1比较简单:

  • 固定31天,年份仅限2020-2030,没有日期合法性验证。

数据模型处理:

  • Pro版本:使用动态数组作为数据源,实现了日期联动(年月变化时自动更新日期),包含了获取月份天数的辅助函数
  • 示例1版本:使用静态数组和固定数字作为数据源

运行效果


结语

本文侧重介绍Tumbler控件的实际应用场景。包括日期选择器、颜色选择器、设置选择器,以及额外完善了日期选择器,实现了完整的功能以及对外观进行了样式优化。

完整工程下载:

https://gitcode.com/u011186532/qml_demo/tree/main/qml_tumbler

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Quz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值