当前位置:网站首页>Qt编写自定义控件-自绘电池
Qt编写自定义控件-自绘电池
2022-07-01 05:35:00 【my_angle2016】
完整代码
battery.h
#ifndef BATTERY_H
#define BATTERY_H
#include <QMainWindow>
class Battery : public QMainWindow
{
Q_OBJECT
public:
Battery(QWidget *parent = nullptr);
~Battery();
void SetValue(int currentValue);
int GetValue();
protected:
void paintEvent(QPaintEvent *);
void drawBorder(QPainter *painter);
void drawBg(QPainter *painter);
void drawText(QPainter *painter);
private slots:
void inputValue();
private:
double _currentValue;
int _margin;
double _minValue; //最小值
double _maxValue; //最大值
bool _isForward; //是否往前移
int _batteryWidth;
int _batteryHeight;
QRectF batteryRect; //电池主体区域
QTimer *inputTimer; //绘制定时器
};
#endif // BATTERY_H
battery.cpp
#pragma execution_character_set("utf-8")
#include "battery.h"
#include "qpainter.h"
#include "qtimer.h"
#include "qdebug.h"
Battery::Battery(QWidget *parent)
: QMainWindow(parent)
, _currentValue(10)
, _margin(3)
, _minValue(0)
, _maxValue(100)
, _isForward(true)
, _batteryWidth(50)
, _batteryHeight(20)
{
// ui->setupUi(this); //驱动UI设计师
// setFixedSize(300, 180); //固定大小
setBaseSize(350, 180);
///--设置了个定时器,周期 10ms ,输入值 inputValue()
inputTimer = new QTimer(this);
inputTimer->setInterval(100);
connect(inputTimer, SIGNAL(timeout()), this, SLOT(inputValue())); //定时100ms调用1次inputValue
inputTimer->start();
}
Battery::~Battery()
{
if (inputTimer->isActive()) {
inputTimer->stop();
}
}
void Battery::SetValue(int currentValue)
{
_currentValue = currentValue;
}
int Battery::GetValue()
{
return _currentValue;
}
///--1. 绘制事件
/*只要窗口部件需要被重绘就被调用, 每个要显示输出的窗口部件必须实现它。
这个事件处理器可以在子类中被重新实现来接收绘制事件。 它可以是repaint()或update()的结果。
很多窗口部件在当它们被请求时,它们很简单地重新绘制整个界面,但是一些窗口部件通过仅仅绘制被请求的区域QPaintEvent::region()进行优化,例如,QListView和QCanvas就是这样做的。
原文链接:https://blog.csdn.net/u012151242/article/details/78947024
*/
void Battery::paintEvent(QPaintEvent *)
{
//绘制准备工作,启用反锯齿
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
///--1.1 绘制边框和头部
drawBorder(&painter);
///--1.2 绘制填充
drawBg(&painter);
///--1.3 内部百分比
drawText(&painter);
}
///--1.1 绘制边框和头部
void Battery::drawBorder(QPainter *painter)
{
//保存状态
painter->save();
//设置笔的颜色和粗细
painter->setPen(QPen(Qt::gray, 5));
//没有画刷填充
painter->setBrush(Qt::NoBrush);
//绘制给定的圆角矩形 矩形 xRadius yRadius
// painter->drawRoundedRect(batteryRect, borderRadius, borderRadius);
//电池边框居中
batteryRect = QRectF((width()-_batteryWidth)/2, (height()-_batteryHeight)/2, _batteryWidth, _batteryHeight);
painter->drawRoundedRect(batteryRect, 2, 2);
//电池头部:画一条直线
painter->setPen(QPen(Qt::gray, 5));
QLineF line(batteryRect.topRight().x()+5, batteryRect.topRight().y()+5, batteryRect.topRight().x()+5, batteryRect.bottomRight().y()-5);
painter->drawLine(line);
//回复保存的状态
painter->restore();
}
///--1.2 绘制填充
void Battery::drawBg(QPainter *painter)
{
painter->save();
//确定画刷颜色
if(_currentValue<=10) {
painter->setBrush(QColor(204, 38, 38)); //红
}
else if (_currentValue <= 20) {
painter->setBrush(QColor(198, 163, 0)); //黄
}
else {
painter->setBrush(QColor(50, 205, 51)); //绿
}
//当前电量转化为宽
double width = _currentValue * (batteryRect.width() - (_margin * 2)) / 100;
//确定左上角位置
QPointF topLeft(batteryRect.topLeft().x() + _margin, batteryRect.topLeft().y() + _margin);
//确定变化的右下角, 最小给个10, 显示内部的填充
QPointF bottomRight(batteryRect.topLeft().x() + width + _margin, batteryRect.bottomRight().y() - _margin);
QRectF rect(topLeft, bottomRight);
//没有线宽
painter->setPen(Qt::NoPen);
painter->drawRoundedRect(rect, 5, 5);
painter->restore();
}
///--1.3 内部百分比
void Battery::drawText(QPainter *painter) {
painter->save();
painter->setPen(Qt::black);
painter->setFont(QFont("Arial",11));
QString value = QString::number(_currentValue) + "%";
//文本居中的好方法
painter->drawText(batteryRect,Qt::AlignCenter,value);
painter->restore();
}
//1. 驱动、输入
void Battery::inputValue()
{
/* if(_isForward) _currentValue += 1;
else _currentValue -= 1;
if(_currentValue >= 45) {
_currentValue = 45;
_isForward = false;
}
if(_currentValue <= _minValue) {
_currentValue = _minValue;
_isForward = true;
}*/
_currentValue = GetValue();
if(_currentValue >= 100) {
_currentValue = 100;
_isForward = false;
}
if(_currentValue <= _minValue) {
_currentValue = _minValue;
_isForward = true;
}
//重绘,将调用paintEvent()函数
this->update();
}
调用过程
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "battery.h"
Battery *battery;
int g_currentValue = 10;
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
battery = new Battery();
battery->setGeometry(rect().x()+500, rect().y()+10,
400, 300);
battery->setParent(this);
inputTimer = new QTimer(this);
inputTimer->setInterval(100);
connect(inputTimer, SIGNAL(timeout()), this, SLOT(inputValue())); //定时100ms调用1次inputValue
inputTimer->start();
}
Widget::~Widget()
{
delete ui;
}
void Widget::inputValue()
{
if(g_currentValue <=0)
g_currentValue = 100;
else
g_currentValue -=1;
battery->SetValue(g_currentValue);
}运行效果截图

边栏推荐
- 【考研高数 自用】高数第一章基础阶段思维导图
- Educational administration management system of SSM (free source code)
- Fluentd is easy to use. Combined with the rainbow plug-in market, log collection is faster
- printk 调试总结
- Web Security (x) what is OAuth 2.0?
- Use and principle of AQS related implementation classes
- How to select conductive slip ring material
- 使用 Nocalhost 开发 Rainbond 上的微服务应用
- 【医学分割】u2net
- Learn the customization and testing of fpga---ram IP from the bottom structure
猜你喜欢

Dynamic verification of new form items in El form; El form verifies that the dynamic form V-IF does not take effect;

eBPF Cilium实战(2) - 底层网络可观测性

基于微信小程序的青少年生理健康知识小助手(免费获取源码+项目介绍+运行介绍+运行截图+论文)

数字金额加逗号;js给数字加三位一逗号间隔的两种方法;js数据格式化

Leetcode top 100 questions 1 Sum of two numbers

Application of industrial conductive slip ring

Mongodb學習篇:安裝後的入門第一課

Trust guessing numbers game

How to create a progress bar that changes color according to progress

Numeric amount plus comma; JS two methods of adding three digits and a comma to numbers; JS data formatting
随机推荐
Things generated by busybox
Unity项目心得总结
移动端常用解决方案
Rust hello-word
云原生存储解决方案Rook-Ceph与Rainbond结合的实践
[ffmpeg] [reprint] image mosaic: picture in picture with wheat
Mongodb learning chapter: introduction after installation lesson 1
Wild melon or split melon?
CentOS 7使用yum安装PHP7.0
Simple implementation of database connection pool
Flutter 实现每次进来界面都刷新数据
idea启动查看项目端口
Thread process foundation of JUC
2022.6.30-----leetcode. one thousand one hundred and seventy-five
导数的左右极限和左右导数的辨析
C WPF uses dockpanel to realize screenshot box
HCM 初学 ( 一 ) - 简介
HDU - 1069 Monkey and Banana(DP+LIS)
Redis数据库的部署及常用命令
[RootersCTF2019]babyWeb