• 036-第三代软件开发-系统时间设置


    头图

    第三代软件开发-系统时间设置


    关键字: QtQmlTime时间系统

    项目介绍

    欢迎来到我们的 QML & C++ 项目!这个项目结合了 QML(Qt Meta-Object Language)和 C++ 的强大功能,旨在开发出色的用户界面和高性能的后端逻辑。

    在项目中,我们利用 QML 的声明式语法和可视化设计能力创建出现代化的用户界面。通过直观的编码和可重用的组件,我们能够迅速开发出丰富多样的界面效果和动画效果。同时,我们利用 QML 强大的集成能力,轻松将 C++ 的底层逻辑和数据模型集成到前端界面中。

    在后端方面,我们使用 C++ 编写高性能的算法、数据处理和计算逻辑。C++ 是一种强大的编程语言,能够提供卓越的性能和可扩展性。我们的团队致力于优化代码,减少资源消耗,以确保我们的项目在各种平台和设备上都能够高效运行。

    无论您是对 QML 和 C++ 开发感兴趣,还是需要我们为您构建复杂的用户界面和后端逻辑,我们都随时准备为您提供支持。请随时联系我们,让我们一同打造现代化、高性能的 QML & C++ 项目!

    重要说明☝

    ☀该专栏在第三代软开发更新完将涨价

    系统时间设置

    因为Qt目前好像没有针对这个的库,所以目前的实现是基于Linux的,准确是是Ubuntu22.04版本。

    演示效果

    这是来之我们公司小伙伴的作品,我们今天就学习一下。顺带Review一下,看看能不能发现什么BUG。

    其实之前这位小伙伴搞复杂了,想着用什么控件啥的,其实Linux是啥,最便捷的就只指令代码,我最开始给他的就是前端qml吧界面撸出来,后端发个指令设置下时间就OK了,不过看他第一版的时候好像整了不少东西,后面好像改成指令。

    QML 实现

    你看看,少叮嘱一句也不行,上来就给我手撸一个Tumbler;

    image-20230802222951242

    这里要给大家推荐一下Qt Desing Studio,不是说这个有多香,反正我是不喜欢用,qml 我都是纯手撸代码,如果我们不知道一个东西Qt 到底有没有给我们实现的时候,可以用它看看。

    image-20230802223133203

    你看,这不Qt已经为咱们写了吗。

    image-20230802223306086

    不过小伙伴写都写了,咱们还是看一下吧

    小伙伴自创 Tumbler
    import QtQuick 2.12
    import QtQuick.Layouts 1.12
    
    Rectangle {
        id: rootRec
        color: "transparent"
    
        property int min: -1
        property int max: -1
        property int current: -1
        property int zero: 0
    
        //获取最终结果
        function getResult(){
            return (myPathView.currentIndex + root.min)
        }
    
        ColumnLayout{
            anchors.fill: parent
    
            Item {
                Layout.fillHeight: true
                Layout.fillWidth: true
                Layout.margins: 10
    
                PathView{
                    id: myPathView
                    anchors.fill: parent
                    currentIndex:  (-1 === rootRec.current) ? 0 : (rootRec.current - rootRec.min)
                    onCurrentIndexChanged: { rootRec.current = currentIndex + rootRec.min; }
                    model: (rootRec.max - rootRec.min + 1)
    
                    delegate: Item{//
                        width:myPathView.width/2
                        height:myPathView.height/myPathView.pathItemCount
    
                        scale: PathView.iconScale!==undefined?PathView.iconScale:1
                        opacity: PathView.iconOpacity!==undefined?PathView.iconOpacity:1
                        z:PathView.iconZ!==undefined?PathView.iconZ:1
                        transform: Rotation {
                            origin.x: width/2
                            origin.y: height/2
                            axis.x: 1
                            axis.y: 0
                            axis.z: 0
                            angle: PathView.iconAngle!==undefined?PathView.iconAngle:0
                        }
    
                        Text{
                            id:timeText
                            anchors.centerIn: parent
                            text: String(Number(modelData) + rootRec.min).padStart(rootRec.zero, '0')
                            color: PathView.isCurrentItem ? "#0099ff" : Qt.lighter("#FFFFFF")
                            font.pixelSize: 20
                            verticalAlignment: Text.AlignVCenter
                            horizontalAlignment: Text.AlignHCenter
                        }
                    }
    
                    pathItemCount: 5
                    preferredHighlightBegin: 0.5
                    preferredHighlightEnd: 0.5
                    highlightRangeMode: PathView.StrictlyEnforceRange
    
                    //交互属性,支持拖动等……
                    interactive: true
                    //滑动速度
                    maximumFlickVelocity:100
    
                    path :pathVertical
                    Path{//------------垂直变化------------
                        id:pathVertical
                        property int height: myPathView.height
                        startX: myPathView.width/2
    
                        PathLine { id:line1; x: pathVertical.startX; y: pathVertical.startY; }
                        PathAttribute { name: "iconZ"; value: 1 }
                        PathAttribute { name: "iconScale"; value: 0.6 }
                        PathAttribute { name: "iconOpacity"; value: 0.3 }
                        PathAttribute { name: "iconAngle"; value: 80  }
                        PathPercent { value: 0 }
    
                        // start scaling up
                        PathLine { id:line2; x: line1.x; y: line1.y + pathVertical.height; }
                        PathAttribute { name: "iconZ"; value: 2 }
                        PathAttribute { name: "iconScale"; value: 0.8 }
                        PathAttribute { name: "iconOpacity"; value: 0.4 }
                        PathAttribute { name: "iconAngle"; value: 50  }
                        PathPercent { value: 1/4 }
    
                        // middle point
                        PathLine { x: line2.x; y: line2.y; }
                        PathAttribute { name: "iconZ"; value: 5 }
                        PathAttribute { name: "iconScale"; value: 1.0 }
                        PathAttribute { name: "iconOpacity"; value:1.0 }
                        PathAttribute { name: "iconAngle"; value: 0  }
                        PathPercent { value: 2/4}
    
                        // start scaling down
                        PathLine { x: line2.x; y: line2.y; }
                        PathAttribute { name: "iconZ"; value: 2 }
                        PathAttribute { name: "iconScale"; value: 0.8}
                        PathAttribute { name: "iconOpacity"; value: 0.4 }
                        PathAttribute { name: "iconAngle"; value: -50  }
                        PathPercent { value: 3/4 }
    
                        // last point
                        PathLine { x: line2.x; y: line2.y; }
                        PathAttribute { name: "iconZ"; value: 1 }
                        PathAttribute { name: "iconScale"; value: 0.6 }
                        PathAttribute { name: "iconOpacity"; value:0.3 }
                        PathAttribute { name: "iconAngle"; value: -80  }
                        PathPercent { value: 1}
                    }
    
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    Qt 家 Tumbler

    通过帮助文档,咱们可以看到有两个版本的 Tumbler,如下图所示

    image-20230802224628692

    • Controls 版本

    image-20230802224740546

    示例代码如下:

     import QtQuick 2.12
     import QtQuick.Window 2.2
     import QtQuick.Controls 2.12
    
     Rectangle {
         width: frame.implicitWidth + 10
         height: frame.implicitHeight + 10
    
         function formatText(count, modelData) {
             var data = count === 12 ? modelData + 1 : modelData;
             return data.toString().length < 2 ? "0" + data : data;
         }
    
         FontMetrics {
             id: fontMetrics
         }
    
         Component {
             id: delegateComponent
    
             Label {
                 text: formatText(Tumbler.tumbler.count, modelData)
                 opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
                 horizontalAlignment: Text.AlignHCenter
                 verticalAlignment: Text.AlignVCenter
                 font.pixelSize: fontMetrics.font.pixelSize * 1.25
             }
         }
    
         Frame {
             id: frame
             padding: 0
             anchors.centerIn: parent
    
             Row {
                 id: row
    
                 Tumbler {
                     id: hoursTumbler
                     model: 12
                     delegate: delegateComponent
                 }
    
                 Tumbler {
                     id: minutesTumbler
                     model: 60
                     delegate: delegateComponent
                 }
    
                 Tumbler {
                     id: amPmTumbler
                     model: ["AM", "PM"]
                     delegate: delegateComponent
                 }
             }
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    当然,我们也可以自定义 Tumbler,官方示例如下:

    import QtQuick 2.12
     import QtQuick.Controls 2.12
    
     Tumbler {
         id: control
         model: 15
    
         background: Item {
             Rectangle {
                 opacity: control.enabled ? 0.2 : 0.1
                 border.color: "#000000"
                 width: parent.width
                 height: 1
                 anchors.top: parent.top
             }
    
             Rectangle {
                 opacity: control.enabled ? 0.2 : 0.1
                 border.color: "#000000"
                 width: parent.width
                 height: 1
                 anchors.bottom: parent.bottom
             }
         }
    
         delegate: Text {
             text: qsTr("Item %1").arg(modelData + 1)
             font: control.font
             horizontalAlignment: Text.AlignHCenter
             verticalAlignment: Text.AlignVCenter
             opacity: 1.0 - Math.abs(Tumbler.displacement) / (control.visibleItemCount / 2)
         }
    
         Rectangle {
             anchors.horizontalCenter: control.horizontalCenter
             y: control.height * 0.4
             width: 40
             height: 1
             color: "#21be2b"
         }
    
         Rectangle {
             anchors.horizontalCenter: control.horizontalCenter
             y: control.height * 0.6
             width: 40
             height: 1
             color: "#21be2b"
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    这里还有两个更高级的版本,不过我没有用过,咱们帖一下,占点字符空间哈

    If you want to define your own contentItem, use either a ListView or PathView as the root item. For a wrapping Tumbler, use PathView:

    Tumbler {
      id: tumbler
    
      contentItem: PathView {
          id: pathView
          model: tumbler.model
          delegate: tumbler.delegate
          clip: true
          pathItemCount: tumbler.visibleItemCount + 1
          preferredHighlightBegin: 0.5
          preferredHighlightEnd: 0.5
          dragMargin: width / 2
    
          path: Path {
              startX: pathView.width / 2
              startY: -pathView.delegateHeight / 2
              PathLine {
                  x: pathView.width / 2
                  y: pathView.pathItemCount * pathView.delegateHeight - pathView.delegateHeight / 2
              }
          }
    
          property real delegateHeight: tumbler.availableHeight / tumbler.visibleItemCount
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    For a non-wrapping Tumbler, use ListView:

    Tumbler {
      id: tumbler
    
      contentItem: ListView {
          model: tumbler.model
          delegate: tumbler.delegate
    
          snapMode: ListView.SnapToItem
          highlightRangeMode: ListView.StrictlyEnforceRange
          preferredHighlightBegin: height / 2 - (height / tumbler.visibleItemCount / 2)
          preferredHighlightEnd: height / 2 + (height / tumbler.visibleItemCount / 2)
          clip: true
      }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • Extras版本

    image-20230802225259942

    官方示例如下:

    The Tumbler control is used with one or more TumblerColumn items, which define the content of each column:

     Tumbler {
         TumblerColumn {
             model: 5
         }
         TumblerColumn {
             model: [0, 1, 2, 3, 4]
         }
         TumblerColumn {
             model: ["A", "B", "C", "D", "E"]
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    You can also use a traditional model with roles:

     Rectangle {
         width: 220
         height: 350
         color: "#494d53"
    
         ListModel {
             id: listModel
    
             ListElement {
                 foo: "A"
                 bar: "B"
                 baz: "C"
             }
             ListElement {
                 foo: "A"
                 bar: "B"
                 baz: "C"
             }
             ListElement {
                 foo: "A"
                 bar: "B"
                 baz: "C"
             }
         }
    
         Tumbler {
             anchors.centerIn: parent
    
             TumblerColumn {
                 model: listModel
                 role: "foo"
             }
             TumblerColumn {
                 model: listModel
                 role: "bar"
             }
             TumblerColumn {
                 model: listModel
                 role: "baz"
             }
         }
     } 
     
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    C++ 端实现

    哎,甭管那些了,总之目前是实现了功能了,咱们还是看看C++端的实现代码吧,后期如果有机会,我在尝试下

    /**
     * @brief XXXX::updateTime
     * @param strTime
     * @return
     * 更新时间
     */
    int XXXX::updateTime(QString strTime)
    {
        QString strDate = strTime.split(" ").at(0);
        QString strTimer = strTime.split(" ").at(1);
    
        QString year = strDate.split("-").at(0);        //年
        QString month = strDate.split("-").at(1);       //月
        QString day = strDate.split("-").at(2);         //日
        QString hour = strTimer.split(":").at(0);       //时
        QString min = strTimer.split(":").at(1);        //分
        QString second = strTimer.split(":").at(2);     //秒
    
        QString a = "date -s" + year + "/" + month + "/" + day;
        QString b = "date -s" + hour + ":" + min + ":" + second;
    
        char *ch;
        QByteArray ba = a.toLatin1();
        ch = ba.data();
    
        char *ch_2;
        QByteArray ba_2 = b.toLatin1();
        ch_2 = ba_2.data();
    
        system(ch);
        system(ch_2);
    
        //强制写入到CMOS
        system("hwclock -w");
    
        return 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    如我所愿,最后还是还是用了指令的方式实现了。

    总结一下

    不尽人意。目前功能开发工作量比较大,先这么滴吧,以实现功能优先,后期再重构。目前这个我也只能分享官方的示例代码,我没有实际写过这个模块。小弟也没有问我,而我也在忙着撸自己的KPI,没有及时Review他的代码,看到实现功能就给过了,没想到呀,不过其实也如你所愿,可能我们的领导并不关注我们的实现方式是否合理,在某一特定条件下,他可能更看重结果。不顾纸是包不住火的,在他时间宽裕的时候,总是会在回头看看的,所以小伙伴们,在条件的允许的情况下,还是要确保你的代码尽可能的合理。


    博客签名2021
  • 相关阅读:
    Android三种数据存储的方式
    一篇万字博文带你入坑爬虫这条不归路 【万字图文】
    自动化测试转型过程中遇到的困难,如何去克服
    真“火爆”还是假“繁荣” 用数据观察Art Gobblers
    Android . java中解析json数据中文变成问号
    更高效的构建工具-vite
    番外篇 | 基于改进YOLOv5的安全帽佩戴检测 | 重参数化结构RepVGG + 空间对象注意力机制RCS-OSA模块
    苹果手机照片如何导入电脑?无损快速的传输办法分享!
    工作中对InheritableThreadLocal使用的思考
    leetcode刷题(第四十八天) 198.打家劫舍 ; 213.打家劫舍II ; 337.打家劫舍III
  • 原文地址:https://blog.csdn.net/z609932088/article/details/134097217