qml 电池控件设计(手把手从零开始)

news2025/3/10 8:15:34

一、说明

做 qt 开发也有好几年了,一直基于QWidget 框架做的开发,使用重写 paint 函数实现各种显示效果,在复杂的 ui 开发中,控件一多或者刷新频率一高,其实也是存在性能限制。
一般来说,qt 的界面对象全部在主线程中运行,main 函数中的 exec()阻塞不断进行事件循环驱动。QWidget的绘制和渲染都是基于 cpu 的,所以这个性能上限吧就感觉相对低点。现在 ui 也是越来越复杂,cpu 压力也就越大。虽然可以通过优化代码提升性能,但是这个浮躁的社会,写起代码来,不得更加浮躁!

然而,qml 居然是使用 gpu 做的渲染,这个是不是就很香了。QWidget 已经n 年没有更新,新的 qt 版本都是围绕 qml 和 3D 做的迭代,感觉 qml 才是qt 的未来。

其实也是断断续续学习过qml,怕年纪越来越大,越不愿意接受新鲜事物,现在还有动力,所以要多做一些学习,并写一些相关的文章记录过程。

之前使用 QWidget 也做过电池控件,有兴趣的朋友可以查看链接:https://blog.csdn.net/weixin_42887343/article/details/113932145

二、效果

在这里插入图片描述

三、需求

  • 最基本的需求就是显示电量了
  • 电量小于 20% 显示橙色,小于 10% 显示红色,否则显示绿色
  • 可以随意设置电池电量
  • 电量变化后,需要有一个渐变的动画
  • 需要显示电池电量百分比文字

四、准备

(1)安装 qtCreator,这个大家应该都没有问题。
(2)使用qtCreator创建 qml 项目,可以参考链接:https://blog.csdn.net/weixin_42887343/article/details/135410332
(3)如果对 qml 不熟悉,可以看一下qml 元素详解:https://blog.csdn.net/weixin_42887343/article/details/135356964

五、代码设计

电池控件的 ui 很简单,可以分成几个部分,电池控件组成结构如下图:

在这里插入图片描述
qml 作为描述性语言,只要使用 qml 对各个部分做一些描述性定义,然后按上图做包含组合即可实现控件。

(1)电池头

    //电池头
    Rectangle {
        id: batteryHeader
        width: batteryContainer.width / 18
        height: batteryContainer.height / 2.5
        anchors.left:batteryContainer.right
        anchors.verticalCenter: batteryContainer.verticalCenter
        color: borderColor
        radius: 5
        Rectangle {
            x: 0
            y: 0
            width: parent.radius
            height: parent.height
            radius: 0
            color: parent.color
        }
    }

(2)电池电量颜色块

	// 电量rect
    Rectangle {
        id:colorRectiud
        width: (batteryContainer.width - 2 * borderWidth)*(batteryLevel)
        height: batteryContainer.height - 2 * borderWidth
        anchors.verticalCenter: parent.verticalCenter
        x: borderWidth
        color: colorBasedOnValue(batteryLevel)
        radius:5
        // 电量颜色获取函数
        function colorBasedOnValue(value) {
            if (value < 0.1) {
                return root.lowerLevelColor;
            } else if (value < 0.2) {
                return root.lowLevelColor;
            } else {
                return root.nomalLevelColor; // 默认值或其他颜色
            }
        }
    }

(3)电池电量文字

	// 电量文字
	Text {
	    anchors.centerIn: parent
	    text: Math.floor(batteryLevel * 100) + "%"
	    font.pixelSize: 20
	    color: "white"
	}

(4)电池体

// 电池体
    Rectangle {
        id: batteryContainer
        width: parent.width - 2 * borderWidth
        height: parent.height - 2 * borderWidth
        anchors.centerIn: parent
        color: borderColor
        border.color: borderColor // 设置边界线颜色
        border.width: borderWidth // 设置边界线宽度
        radius:10
        // 电量rect
        Rectangle {
        ……(2)
        }
        // 电量文字
        Text {
        ……(3)
        }
    }

(5)电池控件

Rectangle {
    id:root
    property real batteryLevel: 1
    property real borderWidth: 6
    property color borderColor: "#aaaaaa"
    property color nomalLevelColor: "#4CAF50"
    property color lowLevelColor: "#FFC107"
    property color lowerLevelColor: "red"

    width: 200
    height: 100

    // 电池体
    Rectangle {
        ……(4)
    }
    //电池头
    Rectangle {
		……(1)
    }
}

说明

代码中,……(1)表示(1)电池头中对应的代码,……(4)表示第四部分电池体的代码,其他同意思。

从上面代码即可看出,他们的组合关系在代码上即为包含关系

控件的总代码:

// Battery.qml

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtGraphicalEffects 1.0

Rectangle {
    id:root
    property real batteryLevel: 1
    property real borderWidth: 6
    property color borderColor: "#aaaaaa"
    property color nomalLevelColor: "#4CAF50"
    property color lowLevelColor: "#FFC107"
    property color lowerLevelColor: "red"

    width: 200
    height: 100

    // 电池体
    Rectangle {
        id: batteryContainer
        width: parent.width - 2 * borderWidth
        height: parent.height - 2 * borderWidth
        anchors.centerIn: parent
        color: borderColor
        border.color: borderColor // 设置边界线颜色
        border.width: borderWidth // 设置边界线宽度
        radius:10
        // 电量rect
        Rectangle {
            id:colorRectiud
            width: (batteryContainer.width - 2 * borderWidth)*(batteryLevel)
            height: batteryContainer.height - 2 * borderWidth
            anchors.verticalCenter: parent.verticalCenter
            x: borderWidth
            color: colorBasedOnValue(batteryLevel)
            radius:5
            // 电量颜色获取函数
            function colorBasedOnValue(value) {
                if (value < 0.1) {
                    return root.lowerLevelColor;
                } else if (value < 0.2) {
                    return root.lowLevelColor;
                } else {
                    return root.nomalLevelColor; // 默认值或其他颜色
                }
            }
        }
        // 电量文字
        Text {
            anchors.centerIn: parent
            text: Math.floor(batteryLevel * 100) + "%"
            font.pixelSize: 20
            color: "white"
        }
    }
    //电池头
    Rectangle {
        id: batteryHeader
        width: batteryContainer.width / 18
        height: batteryContainer.height / 2.5
        anchors.left:batteryContainer.right
        anchors.verticalCenter: batteryContainer.verticalCenter
        color: borderColor
        radius: 5
        Rectangle {
            x: 0
            y: 0
            width: parent.radius
            height: parent.height
            radius: 0
            color: parent.color
        }
    }
}

最后, 上面的控件代码需要使用名为 控件名 的 qml 文件包含,如Battery.qml,并将该文件加入资源文件中,入下图所示:

在这里插入图片描述
这样我们就使用 qml实现了一个电池控件。

六、控件使用

(1)在使用中,我们需要定义一个Slider控件,使用它来控制电池电量。(与电池控件平级)
(2)再定义一个鼠标点击区域MouseArea,将点击区域填充为电池,点击后设置鼠标为随机电量。(需要被电池控件包含)
(3)电池还有需要电池渐变变化,所以还需要添加一个动画元素,设置电池当前电量到设置电量的渐变。(需要被电池控件包含)

总代码如下图:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

Window {
    width: 400
    height: 400
    visible: true
    title: "小小电池控件测试"

    Battery {
        id:batteryID
        anchors.centerIn: parent    //居中于父对象

        PropertyAnimation {         //电量变动动画
            id:batterChange
            target: batteryID
            property: "batteryLevel"
            duration: 500
            easing.type: Easing.InOutQuad
        }
        // 鼠标点击区域
        MouseArea {
            anchors.fill: batteryID
            onClicked: {
                // 模拟电量变化
                batterChange.from=batteryID.batteryLevel    //设置动画初始值
                batterChange.to=Math.random();              //设置动画结束值
                batterChange.start();                       //启动动画
                console.log("batteryLevel changed from "+batterChange.from + " to "+batterChange.to);
            }
        }
    }
    Slider {
        x:batteryID.x
        y:batteryID.y + batteryID.height + 30
        from: 0
        to: 1
        stepSize: 0.01
        value:batteryID.batteryLevel

        onPositionChanged: {
            batteryID.batteryLevel = position;
            console.log("Progress Bar Value:", position);
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1461326.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MKS T3BI集成蝶阀说明T3B-T3PRS-232Supplement

MKS T3BI集成蝶阀说明T3B-T3PRS-232Supplement

洛谷 P1016 [NOIP1999 提高组] 旅行家的预算【贪心】

原题链接&#xff1a;https://www.luogu.com.cn/problem/P1016 题目描述 一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市&#xff08;假设出发时油箱是空的&#xff09;。给定两个城市之间的距离 D1​、汽车油箱的容量 C&#xff08;以升为单位&#xff09;、每升汽…

计网day5

六 传输层 6.1 传输层概述 6.2 UDP协议 6.3 TCP协议 TCP连接管理&#xff1a; TCP可靠传输&#xff1a; TCP拥塞控制&#xff1a;

unity学习(32)——跳转到角色选择界面(父子类问题)

新问题 应该是两个脚本之间缺少继承关系 its children 解决起来很简单&#xff0c;把ResceneScript也绑到canvas上就可以了 。 此时&#xff0c;在账号密码正确的情况下&#xff0c;是可以完成场景切换。 对应的代码如下&#xff1a; TMP_Text d GameObject.FindWithTag(&…

【问题解决】删除node节点后如何把node节点重新加入

环境明细 docker版本&#xff1a; 25.0.3kubeadm 版本&#xff1a;v1.25.0 1 在master节点删除node节点 [rootk8s-master ~]# kubectl delete nodes k8s-node-02 node "k8s-node-02" deleted [rootk8s-master ~]# kubectl get nodes -o wide NAME STAT…

基于 GTSAM 的因子图简单实例

Title: 基于 GTSAM 的因子图简单实例 文章目录 I. 引言II. GTSAM 的安装与配置III. 基于 GTSAM 的因子图实例的 C 实现1. C 源码2. CMakeLists.txt 脚本3. 数值结果 IV. 基于 GTSAM 的因子图实例的 Python 实现1. Python 源码2. 数值结果3. 可视化结果 V. 总结 关联博文: 因子图…

day2:信号与槽

思维导图 使用手动连接&#xff0c;将登录框中的取消按钮使用t4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断u界面上输入的账号是否为"123",密码是否为"…

springboot集成JWT实现token权限认证

vuespringboot登录与注册功能的实现 注&#xff1a;对于JWT的学习&#xff0c;首先要完成注册和登录的功能&#xff0c;本篇博客是基于上述博客的进阶学习&#xff0c;代码页也是在原有的基础上进行扩展 ①在pom.xml添加依赖 <!-- JWT --> <dependency><grou…

【Linux】git操作 - gitee

1.使用 git 命令行 安装 git yum install git 2.使用gitee 注册账户 工作台 - Gitee.com 进入gitee&#xff0c;根据提示注册并登录 新建仓库 仓库名称仓库简介初始换仓库 3.Linux-git操作 进入仓库&#xff0c;选择“克隆/下载” 复制下面的两行命令进行git配置 然后将仓库clo…

Vue3引用第三方模块报错Could not find a declaration file for module ***.

在引用第三方的组件时候报错如下 原因是&#xff1a;该组件可能不是.ts文件而是.js文件 解决方案&#xff1a; 1.在Src的目录下面新建一个文件为shims-vue.d.ts的文件 2.文件内容为 declare module xxx&#xff0c;xxx就是你报错的模块 例如我这样 declare module vue3-pu…

【C语言】中的位操作符和移位操作符,原码反码补码以及进制之间的转换

欢迎大家来到c语言知识小课堂&#xff0c;今天的知识点是操作符和进制 目录 一、进制之间的转化1、什么是二进制&#xff0c;八进制&#xff0c;十进制&#xff0c;十六进制2、进制之间的转化其他进制转化为十进制十进制转化为二进制二进制转化为八进制八进制转化为二进制二进…

2023年最新阿里云服务器价格表(配置价格+磁盘+带宽)

2024年阿里云服务器租用价格表更新&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年、ECS u1实例2核4G、5M固定带宽、80G ESSD Entry盘优惠价格199元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元、2核4G4M带宽轻量服务器一年165元12个月、2核4G服…

P2957 [USACO09OCT] Barn Echoes G

P2957 [USACO09OCT] Barn Echoes G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P2957 题目分析 对于求单个字符串的哈希值相当于求前缀和&#xff0c;而求单个字符串的子串的哈希值则相当于求其区间和&#xff1b; 那么只需求两个…

fail-safe机制与fail-fast机制分别有什么作用

fail-safe和fail-fast&#xff0c;是多线程并发操作集合时的一种失败处理机制。 Fail-fast&#xff1a;表示快速失败&#xff0c;在集合遍历过程中&#xff0c;一旦发现容器中的数据被修改了&#xff0c;会立刻抛出ConcurrentModificationException异常&#xff0c;从而导致遍…

Selenium基于Python web自动化测试框架 -- PO

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

代码随想录第二十一天 701.二叉搜索树中的插入操作 108.将有序数组转换为二叉搜索树

701.二叉搜索树中的插入操作 题目描述 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入树中的值 value &#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 &#xff0c;新值和原始二叉搜索树中的任意节点值都不同。 注意&a…

CF1468J Road Reform 题解

CF1468J Road Reform 题解 link CF1468J Road Reform 题面翻译 给定一个有 n n n 个节点&#xff0c; m m m 条无向带权边的图&#xff0c;和一个参数 k k k&#xff0c;第 i i i 条边权值为 s i s_i si​。 现在你要保留这个图中的 n − 1 n-1 n−1 条边使得这个图变…

306_C++_QT_创建多个tag页面,使用QMdiArea容器控件,每个页面都是一个新的表格[或者其他]页面

程序目的是可以打开多个styles文件(int后缀文件),且是tag样式的(就是可以切多个页面出来,并且能够单独关闭);其中读取ini文件,将其插入到表格中的操作,也是比较复杂的,因为需要保持RGB字符串和前面的说明字符串对齐 ini文件举例: [MainMenu] Foreground\Selected=&…

63-JQuery语法,选择器,事件,方法,遍历循环each

1.一个JS库,用js封装很多的方法放到一个文件里面,直接拿了用就可以 文件名带min是压缩过的不带min是没压缩过的 2.JQuery语法 通过选取HTML元素,并对选取的元素执行某些操作 基础语法:$(selector).action() <!-- 需要把JQuery文件先引入才能用 --><script src…

Project_Euler-06 题解

Project_Euler-06 题解 题目描述 两个公式 等差数列求和公式 i i i项&#xff1a; a i a_{i} ai​ 项数&#xff1a; n n n 公差&#xff1a; d d d 和&#xff1a; S n S_{n} Sn​ a n a 1 ( n − 1 ) d S n n ( a 1 a n ) 2 a_{n} a_{1} (n - 1)d\\ S_{n} \frac{n(a_…