qt drawtext 颜色_Qt编写自定义控件14-环形进度条

前言

环形进度条,用来展示当前进度,为了满足大屏UI的需要特意定制,以前有个叫圆环进度条,不能满足项目需要,只能重新定做,以前的进度间距不能自适应分辨率,而且当前进度对应的反的进度不能单独设置颜色,即当前进度90%,剩余的10%也需要设置成不同的颜色,还有一个重要的功能是,能够指定多个警戒值,一旦超过或者小于该值,则当前进度自动切换到预先设定的警戒值颜色,而不需要用户自己去判断警戒值去设置警戒颜色,用户只需要传入当前值即可,这个功能非常实用,还可以设置警戒判断的标准是超过值还是小于值报警。个人感觉这个环形进度条功能完爆市面上所有的圆环进度条。只要稍作参数设置可以变成各种想要的效果,什么起始角度+动画效果+顺时针逆时针转等。

实现的功能

  • 1:可设置范围值,支持负数值
  • 2:可设置精确度,最大支持小数点后3位
  • 3:可设置起始角度
  • 4:可设置三种值+三种颜色,启用自动检测值后绘制不同的颜色
  • 5:可设置是否启用动画效果以及动画效果每次移动的步长
  • 6:可设置背景颜色/文字颜色/进度颜色/中间圆颜色
  • 7:可设置值警戒报警比较模式 0-不比较 1-最大值报警 2-最小值报警
  • 8:可设置显示的值是百分比
  • 9:可设置圆环与背景之间的距离即间距
  • 10:可设置圆环的宽度
  • 11:可设置圆环背景颜色,形成两种颜色差
  • 12:可设置顺时针逆时针转
  • 13:自适应窗体拉伸,刻度尺和文字自动缩放

效果图

2f0947da0feda46d4416d4361834006e.gif
a74a84cee0472d95b5af4a95dd9238c1.png

核心代码

void ProgressRing::paintEvent(QPaintEvent *){ int width = this->width(); int height = this->height(); int side = qMin(width, height); //绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放 QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); painter.translate(width / 2, height / 2); painter.scale(side / 200.0, side / 200.0); //绘制背景 drawBg(&painter); //绘制进度 drawRing(&painter); //绘制间隔,重新绘制一个圆遮住,产生间距效果 if (ringPadding > 0) { drawPadding(&painter); } //绘制中间圆 drawCircle(&painter); //绘制当前值 drawValue(&painter);}void ProgressRing::drawBg(QPainter *painter){ int radius = 99; painter->save(); painter->setPen(Qt::NoPen); //这里有个技巧,如果没有间距则设置成圆环的背景色 painter->setBrush(ringPadding == 0 ? ringBgColor : bgColor); painter->drawEllipse(-radius, -radius, radius * 2, radius * 2); painter->restore();}void ProgressRing::drawRing(QPainter *painter){ int radius = 99 - ringPadding; painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(ringColor); QRectF rect(-radius, -radius, radius * 2, radius * 2); //计算总范围角度,当前值范围角度,剩余值范围角度 double angleAll = 360.0; double angleCurrent = angleAll * ((currentValue - minValue) / (maxValue - minValue)); double angleOther = angleAll - angleCurrent; //如果逆时针 if (!clockWise) { angleCurrent = -angleCurrent; angleOther = -angleOther; } //动态设置当前进度颜色 QColor color = ringColor; if (alarmMode == 1) { if (currentValue >= ringValue3) { color = ringColor3; } else if (currentValue >= ringValue2) { color = ringColor2; } else { color = ringColor1; } } else if (alarmMode == 2) { if (currentValue <= ringValue1) { color = ringColor1; } else if (currentValue <= ringValue2) { color = ringColor2; } else { color = ringColor3; } } //绘制当前值饼圆 painter->setBrush(color); painter->drawPie(rect, (startAngle - angleCurrent) * 16, angleCurrent * 16); //绘制剩余值饼圆 painter->setBrush(ringBgColor); painter->drawPie(rect, (startAngle - angleCurrent - angleOther) * 16, angleOther * 16); painter->restore();}void ProgressRing::drawPadding(QPainter *painter){ int radius = 99 - ringWidth - ringPadding; painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(bgColor); painter->drawEllipse(-radius, -radius, radius * 2, radius * 2); painter->restore();}void ProgressRing::drawCircle(QPainter *painter){ //文字的区域要减去进度的宽度及间距 int radius = 99 - ringWidth - (ringPadding * 2); painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(circleColor); painter->drawEllipse(-radius, -radius, radius * 2, radius * 2); painter->restore();}void ProgressRing::drawValue(QPainter *painter){ //文字的区域要减去进度的宽度及间距 int radius = 99 - ringWidth - (ringPadding * 2); painter->save(); painter->setPen(textColor); QFont font; int fontSize = radius - (showPercent ? 20 : 6); font.setPixelSize(fontSize); painter->setFont(font); QRectF textRect(-radius, -radius, radius * 2, radius * 2); QString strValue; if (showPercent) { double percent = (currentValue * 100) / (maxValue - minValue); strValue = QString("%1%").arg(percent, 0, 'f', precision); } else { strValue = QString("%1").arg(currentValue, 0, 'f', precision); } painter->drawText(textRect, Qt::AlignCenter, strValue); painter->restore();}

欢迎提出改进意见,谢谢!

旋转仪表盘是一种常见的显示控件,可以用来展示一些数据,如速度、油量、温度等,下面我将介绍如何使用Qt编写一个旋转仪表盘控件。 首先,我们需要在Qt中创建一个新的自定义控件类。可以通过Qt Creator中的“添加新文件”功能来创建一个QWidget派生类。在这个类中,我们需要实现paintEvent()函数来绘制仪表盘。 在paintEvent()函数中,我们可以使用QPainter来绘制仪表盘的各个部分,包括刻度线、指针、文字等。具体实现可以参考以下代码: ```C++ void RotatingDial::paintEvent(QPaintEvent *event) { // 设置背景色 QPalette pal(palette()); pal.setColor(QPalette::Background, Qt::white); setAutoFillBackground(true); setPalette(pal); // 绘制刻度线 QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); painter.translate(width() / 2, height() / 2); painter.setPen(QPen(Qt::black, 2)); for (int i = 0; i < 60; i++) { painter.drawLine(0, -100, 0, -90); painter.rotate(6); } // 绘制指针 painter.save(); painter.rotate(m_angle); painter.setBrush(Qt::red); painter.setPen(Qt::NoPen); painter.drawConvexPolygon(m_pointer, 3); painter.restore(); // 绘制文字 QFont font("Arial", 12, QFont::Bold); painter.setFont(font); painter.drawText(-30, 50, "Speed"); } ``` 在上面的代码中,我们首先设置了控件的背景色为白色。然后使用QPainter绘制了60条刻度线,并旋转6度。接着,我们绘制了一个红色的指针,并根据m_angle属性来旋转指针的角度。最后,我们使用QPainter绘制了文字“Speed”。 在我们的自定义控件中,我们需要一个属性来控制指针的角度。我们可以使用Q_PROPERTY宏来定义这个属性,例如: ```C++ class RotatingDial : public QWidget { Q_OBJECT Q_PROPERTY(int angle READ angle WRITE setAngle) public: RotatingDial(QWidget *parent = nullptr); int angle() const; void setAngle(int angle); private: int m_angle; QPolygon m_pointer; }; ``` 在上面的代码中,我们使用Q_PROPERTY宏定义了angle属性,并提供了getter和setter函数。我们还定义了一个私有变量m_angle来存储当前的角度,以及一个QPolygon对象m_pointer来存储指针的形状。 在setAngle()函数中,我们设置m_angle属性,并根据新的角度计算指针的位置: ```C++ void RotatingDial::setAngle(int angle) { if (angle != m_angle) { m_angle = angle; m_pointer.setPoint(0, QPoint(0, -90)); m_pointer.setPoint(1, QPoint(5, 0)); m_pointer.setPoint(2, QPoint(-5, 0)); m_pointer.translate(0, 100); update(); } } ``` 在上面的代码中,我们首先判断新的角度是否与当前的角度相同。如果不同,我们就更新m_angle属性,并重新计算指针的位置。最后,我们调用update()函数来触发paintEvent()函数的调用,从而完成控件的重绘。 最后,我们可以在MainWindow类中使用我们的自定义控件,例如: ```C++ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { RotatingDial *dial = new RotatingDial(this); dial->setAngle(30); QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(dial); setCentralWidget(new QWidget); centralWidget()->setLayout(layout); } ``` 在上面的代码中,我们创建了一个RotatingDial对象,并设置了初始角度为30度。然后,将其添加到QHBoxLayout布局中,并设置为主窗口的中央控件。 至此,我们已经完成了一个简单的旋转仪表盘的自定义控件。你可以根据需要对其进行扩展和优化,使其更加适合你的应用场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值