《Qt/UI美化实战课程》新课首发
(1)无边框窗口(11讲)
(2)图标字体(10讲)
(3)官方图表QChart:曲线、柱状图、饼图(20+讲)
(4)第三方图表QCustomPlot:曲线、柱状图、饼图(20+讲)
(5)监控日志高亮(共 14 讲)
(6)仪表盘(16讲)
(7)天气预报(11+讲)
(8)基础控件(15+讲)
(9)高级控件(12+讲)
(10)精美换肤(15+讲)
详情参见个人主页的置顶视频(明王出品,必属精品)
需要系统跟明王学习的小伙伴:coding4096
(1)总课时:超 120+ 讲,每日更新
(2)讲课风格:从零新建项目,从零一行行写代码
(3)提供资料:视频教程+配套源码+详细笔记
本章将会从零实现一个自定义控件-仪表盘
,它支持:
✅ 自定义起始角度、圆弧跨度
✅ 自定义圆环宽度、颜色、样式
✅ 支持背景圆环、当前值圆环
✅ 自定义刻度线的颜色、位置、大小刻度的数目
✅ 自定义刻度值的颜色、位置、最大最小值、精度(小数位数)
✅ 自定义显示标题:温度、湿度、电流、电压等(标题完美地显示在缺口
处)
✅ 支持动画特性:从一个值变为另一个值,指针会平滑旋转
✅ 支持仪表盘自适应大小(仪表盘缩放时,圆环宽度、刻度线、刻度值、标题大小等,自适应地缩放)
本章会从零开始,自定义实现一个仪表盘控件。会实现的2个效果:
这里做一个动态的效果,如下:
1. 增加动起来复选框
首先,来到 widget.h
,增加一个复选框以及其对应的槽函数,如下:
class Widget : public QWidget
{
private slots:
// 动起来
void onChkShowClicked(bool b);
private:
// 动起来
QCheckBox* chkShow;
};
然后,来到 widget.cpp
,修改 initRight()
函数,如下:
void Widget::initRight()
{
// 5. 弹簧
QSpacerItem* item = new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding);
rightLayout->addItem(item);
// 6. 动态效果展示
QGroupBox* showGroup = new QGroupBox("炫酷动画展示", this);
QHBoxLayout* showLayout = new QHBoxLayout(showGroup);
chkShow = new QCheckBox(this);
showLayout->addWidget(chkShow);
rightLayout->addWidget(showGroup);
}
最后,来到 widget.cpp
,在构造中,绑定复选框的槽函数,如下:
Widget::Widget(QWidget* parent) : QWidget(parent)
{
// 5. 动起来
connect(chkShow, SIGNAL(toggled(bool)), this, SLOT(onChkShowClicked(bool)));
}
2. 让角度动起来
首先,来到 widget.h
,声明相关的成员函数和成员变量,如下:
class Widget : public QWidget
{
private slots:
// 动起来
void onStartAngleTimeout();
private:
// 动起来
// 角度
QTimer* startAngleTimer;
bool incStartAngle;
int cnt;
};
然后,来到 widget.cpp
,实现 onStartAngleTimeout()
槽函数,如下:
void Widget::onStartAngleTimeout()
{
int startAngle = gauge->getStartAngle();
if ( incStartAngle ) {
startAngle++;
if ( startAngle >= 360 ) {
incStartAngle = false;
startAngle = 359;
}
} else {
startAngle--;
if ( startAngle <= 0 ) {
incStartAngle = true;
startAngle = 0;
}
}
gauge->setStartAngle(startAngle); // 设置起始角度
leStartAngle->setText(QString::number(startAngle));
}
不要忘记在 widget.cpp 构造中,创建定时器,绑定超时的槽函数,如下:
Widget::Widget(QWidget* parent) : QWidget(parent)
{
// 5. 动起来
startAngleTimer = new QTimer(this);
incStartAngle = true;
connect(startAngleTimer, &QTimer::timeout, this, &Widget::onStartAngleTimeout);
}
最后,实现 onChkShowClicked() 函数,如下:
void Widget::onChkShowClicked(bool b)
{
if ( b ) {
startAngleTimer->start(100);
} else {
startAngleTimer->stop();
}
}
此时运行,效果如下:
3. 让值动起来
首先,来到 widget.h
,声明相关的成员函数和成员变量,如下:
class Widget : public QWidget
{
private slots:
// 动起来
void onValueTimeout();
private:
// 动起来
// 值
QTimer* valueTimer;
bool incValue;
};
然后,来到 widget.cpp,实现 onValueTimeout() 槽函数,如下:
void Widget::onValueTimeout()
{
QColor colors[4] = {QColor(89, 113, 201), QColor(221, 99, 98), QColor(156, 204, 108), QColor(240, 198, 65)};
PointerStyle pointerStyle[4] = {Circle, Sharp, Circle, Sharp};
Qt::PenCapStyle ringStyle[4] = {Qt::RoundCap, Qt::FlatCap, Qt::RoundCap, Qt::FlatCap};
float value = gauge->getValue();
float step = (gauge->getMaxValue() - gauge->getMinValue()) / (gauge->getMajorScale() * gauge->getMinorScale());
if ( incValue ) {
value += step;
if ( value > gauge->getMaxValue() ) {
value = gauge->getMaxValue();
incValue = false;
}
} else {
value -= step;
if ( value < gauge->getMinValue() ) {
value = gauge->getMinValue();
incValue = true;
cnt = (cnt + 1) % 4;
gauge->setCurrentRingColor(colors[cnt]); // 设置当前圆环颜色
QString currentRingColor = QString("background-color: rgb(%1,%2,%3);").arg(colors[cnt].red()).arg(colors[cnt].green()).arg(colors[cnt].blue());
lblCurrentRingColor->setStyleSheet(currentRingColor);
gauge->setPointerColor(colors[cnt]); // 设置指针颜色
QString pointerColor = QString("background-color: rgb(%1,%2,%3);").arg(colors[cnt].red()).arg(colors[cnt].green()).arg(colors[cnt].blue());
lblPointerColor->setStyleSheet(pointerColor);
gauge->setPointerStyle(pointerStyle[cnt]);
if ( pointerStyle[cnt] == Circle ) {
cboPointerStyle->setCurrentIndex(0);
} else if ( pointerStyle[cnt] == Sharp ) {
cboPointerStyle->setCurrentIndex(1);
}
gauge->setRingStyle(ringStyle[cnt]);
if ( ringStyle[cnt] == Qt::FlatCap ) {
cboRingStyle->setCurrentIndex(0);
} else if ( ringStyle[cnt] == Qt::RoundCap ) {
cboRingStyle->setCurrentIndex(1);
}
}
}
gauge->setValue(value);
int sliderValue = (value - gauge->getMinValue()) / (gauge->getMaxValue() - gauge->getMinValue()) * (slider->maximum() - slider->minimum());
slider->setValue(sliderValue);
}
不要忘记在 widget.cpp 构造中,创建定时器,绑定超时的槽函数,如下:
Widget::Widget(QWidget* parent) : QWidget(parent)
{
// 5. 动起来
valueTimer = new QTimer(this);
incValue = true;
cnt = 0;
connect(valueTimer, &QTimer::timeout, this, &Widget::onValueTimeout);
}
最后,修改 onChkShowClicked()
函数,如下:
void Widget::onChkShowClicked(bool b)
{
if ( b ) {
startAngleTimer->start(100);
valueTimer->start(100);
} else {
startAngleTimer->stop();
valueTimer->stop();
}
}
此时运行,就可以实现开始展示的动画效果了,如下: