zhidao 发表于 2025-2-6 16:42:29

Qml 中实现时间轴组件

【写在前面】

时间轴组件是现代用户界面中常见的元素,用于按时间顺序展示事件。
本文将介绍如何使用 Qml 实现一个灵活且可定制的时间轴组件,并探讨其设计思路和实现细节。
<hr>【正文开始】

效果图


组件概述

我们实现的时间轴组件具有以下特点:

[*]支持自定义节点样式:可以设置节点的图标、背景颜色、边框颜色等。
[*]支持自定义线条样式:可以设置线条的颜色和宽度。
[*]支持自定义时间显示格式:可以设置时间的显示格式和字体样式。
[*]支持自定义内容样式:可以设置内容的背景颜色、边框颜色、字体样式等。
[*]支持正序和倒序排列:可以根据时间戳对事件进行正序或倒序排列。
实现细节

1. 组件结构

时间轴组件的核心是一个 ListView,它用于展示所有的事件项。每个事件项由三个部分组成:

[*]节点:表示事件的时间点,可以是图标或圆形背景。
[*]线条:连接相邻事件的节点。
[*]内容:显示事件的具体内容和时间。
2. 属性定义

组件提供了多个属性来定制时间轴的外观和行为:

[*]节点样式:defaultNodeIconColor、defaultNodeBackgroundRadius、defaultNodeBackgroundColor、defaultNodeBorderColor、defaultNodeBorderWidth。
[*]线条样式:defaultLineColor、defaultLineWidth。
[*]时间样式:defaultTimeFont、defaultTimeFontColor、defaultTimeFormat。
[*]内容样式:defaultContentFormat、defaultContentFont、defaultContentFontColor、defaultContentBackgroundRadius、defaultContentBackgroundColor、defaultContentBorderColor、defaultContentBorderWidth。
3. 数据模型

时间轴组件使用 ListModel 来存储事件数据。每个事件项包含以下属性:

[*]timestamp:事件的时间戳。
[*]content:事件的内容。
[*]nodeOptions:节点的样式选项。
[*]lineOptions:线条的样式选项。
[*]timeOptions:时间的样式选项。
[*]contentOptions:内容的样式选项。
4. 事件项的添加和排序

组件提供了 append 函数来添加新的事件项,并根据时间戳进行排序。sort 函数用于对现有的事件项进行重新排序。
function append(object) {    __initOptions(object);    let index = 0;    let rowCount = listModel.count;    for (let i = 0; i < rowCount; i++) {      if (root.reverse) {            if (listModel.get(i).__timestamp < object.__timestamp) {                index = i + 1;            } else break;      } else {            if (listModel.get(i).__timestamp > object.__timestamp) {                index = i + 1;            } else break;      }    }    listModel.insert(index, object);}function sort() {    let rowCount = listModel.count;    for (let i = 0; i < rowCount; i++) {      for (let j = 0; i + j < rowCount - 1; j++) {            if (root.reverse) {                if (listModel.get(j).__timestamp > listModel.get(j + 1).__timestamp) {                  listModel.move(j, j + 1, 1);                }            } else {                if (listModel.get(j).__timestamp < listModel.get(j + 1).__timestamp) {                  listModel.move(j, j + 1, 1);                }            }      }    }}5. 事件项的渲染

每个事件项通过 Loader 动态加载节点、线条和内容组合组件:
Loader {    id: lineLoader    active: index !== (listModel.count - 1)    width: nodeLoader.width    height: parent.height - nodeLoader.height    anchors.top: nodeLoader.bottom    sourceComponent: lineDelegate    property var lineOptions: __lineOptions}Loader {    id: nodeLoader    sourceComponent: nodeDelegate    property var nodeOptions: __nodeOptions}Loader {    id: contentLoader    anchors.left: nodeLoader.right    anchors.leftMargin: 10    anchors.right: parent.right    sourceComponent: contentDelegate    property var content: __content    property var contentOptions: __contentOptions    property var timestamp: __timestamp    property var timeOptions: __timeOptions}如何使用

我们可以像使用标准的 qml 元素一样使用时间轴组件:
import QtQuick 2.15import QtQuick.Controls 2.15ApplicationWindow {    visible: true    width: 800    height: 600    title: "Timeline Example"    Timeline {      id: timeline      width: 400      anchors.top: row.bottom      anchors.topMargin: 10      anchors.bottom: parent.bottom      anchors.horizontalCenter: parent.horizontalCenter      defaultNodeBackgroundColor: "transparent"      defaultNodeBorderWidth: 1      defaultTimeFormat: "yyyy-MM-dd hh:mm:ss"      initModel: [            {                timestamp: new Date(2024, 7, 1, 1),                content: "更新 Github 模板 1",                nodeOptions: { icon: "\uf27b" }            },            {                timestamp: new Date(2024, 7, 7, 11),                content: "更新 Github 模板 2",                nodeOptions: { backgroundColor: "blue" },                lineOptions: { color: "red" }            },            {                timestamp: new Date(2024, 7, 7, 16),                content: "更新 Github 模板 2",                lineOptions: { width: 5 }            },            {                timestamp: new Date(2024, 7, 9, 5, 30),                content: "更新 Github 模板 3"            },            {                timestamp: new Date(2024, 7, 12, 9),                timeOptions: {                  font: { family: "华文彩云", pointSize: 12 },                  fontColor: "green",                  format: "yyyy-MM-dd hh:mm:ss:zzz"                },                content: "更新 Github 模板 4",            },            {                timestamp: new Date(2024, 7, 12, 18, 30),                content: "更新 Github 模板 5",                contentOptions: {                  font: { family: "微软雅黑", pointSize: 14 },                  fontColor: "red",                  backgroundColor: "#ddd"                }            },            {                timestamp: new Date(2024, 7, 17, 5, 35),                content: "更新 Github 模板 6 ===================================",                contentOptions: {                  borderColor: "#ddd"                }            }      ]    }}<hr>【结语】

通过自定义 Qml 组件,我们实现了一个灵活且可定制的时间轴组件。
该组件不仅支持基本的时间轴功能,还提供了丰富的样式定制选项,能够满足各种实际开发需求。
最后:项目链接(多多star呀..⭐_⭐):
Github: https://github.com/mengps/QmlControls
Gitee: https://gitee.com/MenPenS/QmlControls
页: [1]
查看完整版本: Qml 中实现时间轴组件