• QT中窗口自绘制效果展示


    项目中需要使用QT进行窗口自绘,前期先做一下技术探索,参考相关资料代码熟悉流程。本着代码是最好的老师原则,在此记录一下。

    目录

    1.运行效果

    2.代码结构

    3.具体代码


    1.运行效果

    2.代码结构

    3.具体代码

    myspeed.pro

    1. QT += core gui
    2. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    3. CONFIG += c++17
    4. # You can make your code fail to compile if it uses deprecated APIs.
    5. # In order to do so, uncomment the following line.
    6. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
    7. SOURCES += \
    8. drawdialog.cpp \
    9. main.cpp \
    10. meter1.cpp \
    11. meter2.cpp
    12. HEADERS += \
    13. drawdialog.h \
    14. meter1.h \
    15. meter2.h
    16. # Default rules for deployment.
    17. qnx: target.path = /tmp/$${TARGET}/bin
    18. else: unix:!android: target.path = /opt/$${TARGET}/bin
    19. !isEmpty(target.path): INSTALLS += target

    drawdialog.h

    1. #include
    2. class DrawDialog : public QDialog
    3. {
    4. Q_OBJECT
    5. public:
    6. explicit DrawDialog(QWidget *parent = 0);
    7. void mousePressEvent(QMouseEvent *event);
    8. void mouseMoveEvent(QMouseEvent *event);
    9. void paintEvent(QPaintEvent *event) ;
    10. void keyPressEvent( QKeyEvent * event );
    11. private:
    12. QPoint m_CurrentPos;
    13. };

    meter1.h

    1. #ifndef METER1_H
    2. #define METER1_H
    3. #include
    4. #include
    5. // 仪表盘开发参考博客
    6. // https://blog.csdn.net/yyz_1987/article/details/126958420#comments_29151980
    7. class MyMeter1 : public QWidget
    8. {
    9. Q_OBJECT
    10. public:
    11. MyMeter1(QWidget *parent = 0);
    12. ~MyMeter1();
    13. void setValue(double val);
    14. protected:
    15. void paintEvent(QPaintEvent *);
    16. void drawCrown(QPainter *painter);
    17. void drawBackground(QPainter *painter);
    18. void drawScale(QPainter *painter);
    19. void drawScaleNum(QPainter *painter);
    20. void drawTitle(QPainter *painter);
    21. void drawIndicator(QPainter *painter);
    22. void drawNumericValue(QPainter *painter);
    23. protected:
    24. void mouseMoveEvent(QMouseEvent *event);
    25. void mousePressEvent(QMouseEvent *event);
    26. void mouseReleaseEvent(QMouseEvent *event);
    27. private:
    28. QPoint mousePoint;
    29. bool mouse_press;
    30. private:
    31. QColor m_background;
    32. QColor m_foreground;
    33. int m_maxValue;
    34. int m_minValue;
    35. int m_startAngle;
    36. int m_endAngle;
    37. int m_scaleMajor;
    38. int m_scaleMinor;
    39. double m_value;
    40. int m_precision;
    41. QTimer *m_updateTimer;
    42. QString m_units;
    43. QString m_title;
    44. public Q_SLOTS:
    45. void UpdateAngle();
    46. private:
    47. };
    48. #endif // METER1_H

    meter2.h

    1. #ifndef METER2_H
    2. #define METER2_H
    3. #include
    4. class MyMeter2 : public QWidget
    5. {
    6. Q_OBJECT
    7. public:
    8. MyMeter2(QWidget *parent = nullptr);
    9. ~MyMeter2();
    10. void paintEvent(QPaintEvent *event);
    11. void timerEvent(QTimerEvent *e);
    12. private:
    13. void drawFrame(QPainter *painter);
    14. void drawScale(QPainter *painter);
    15. void drawScaleNum(QPainter *painter);
    16. void drawPointer(QPainter *painter);
    17. void drawSpeed(QPainter *painter);
    18. void drawUnit(QPainter *painter);
    19. int speed;
    20. int time_id;
    21. int status;
    22. qreal m_angle;
    23. QColor m_foreground;
    24. int m_maxValue;
    25. int m_minValue;
    26. int m_startAngle;
    27. int m_endAngle;
    28. int m_scaleMajor;
    29. int m_scaleMinor;
    30. double m_value;
    31. int m_precision;
    32. //QTimer *m_updateTimer;
    33. QString m_units;
    34. QString m_title;
    35. };
    36. #endif // METER2_H

    drawdialog.cpp

    1. #include "drawdialog.h"
    2. #include
    3. #include
    4. #include
    5. DrawDialog::DrawDialog(QWidget *parent) : QDialog(parent)
    6. {
    7. //让程序无边框
    8. setWindowFlags( Qt::FramelessWindowHint );
    9. //让程序背景透明
    10. setAttribute(Qt::WA_TranslucentBackground, true);
    11. }
    12. void DrawDialog::mousePressEvent(QMouseEvent *event)
    13. {
    14. //当鼠标左键按下时,记录当前位置
    15. if(event->button() == Qt::LeftButton)
    16. {
    17. m_CurrentPos = event->globalPos() - frameGeometry().topLeft();
    18. event->accept();
    19. }
    20. QDialog::mousePressEvent(event);
    21. }
    22. void DrawDialog::mouseMoveEvent(QMouseEvent *event)
    23. {
    24. //支持窗体移动
    25. if (event->buttons() & Qt::LeftButton)
    26. {
    27. move(event->globalPos() - m_CurrentPos);
    28. event->accept();
    29. }
    30. QDialog::mouseMoveEvent(event);
    31. }
    32. //绘制图形
    33. void DrawDialog::paintEvent(QPaintEvent *event)
    34. {
    35. QPainter painter(this);
    36. //反走样
    37. painter.setRenderHint(QPainter::Antialiasing,true);
    38. painter.setPen( QPen(Qt::green, 2) );
    39. painter.setBrush( Qt::blue );
    40. QRect rect(10,10,200,260);
    41. //绘制一个椭圆
    42. painter.drawEllipse(rect);
    43. }
    44. void DrawDialog::keyPressEvent( QKeyEvent * event )
    45. {
    46. //按下esc键时,关闭
    47. if(event->key() == Qt::Key_Escape)
    48. {
    49. close();
    50. }
    51. }

    meter1.cpp

    1. #include "meter1.h"
    2. #include
    3. // 构造函数
    4. MyMeter1::MyMeter1(QWidget *parent){
    5. m_background = Qt::black;
    6. m_foreground = Qt::white;
    7. m_startAngle = 60;
    8. m_endAngle = 60;
    9. m_scaleMajor = 10;
    10. m_minValue = 0;
    11. m_maxValue = 100;
    12. m_scaleMajor = 10;//分度
    13. m_scaleMinor = 10;
    14. m_units = "L/min";
    15. m_title = "仪表盘";
    16. m_precision = 0;
    17. m_value = 0;
    18. mouse_press = false;
    19. setWindowFlags(Qt::FramelessWindowHint);//无窗体
    20. setAttribute(Qt::WA_TranslucentBackground);//背景透明
    21. resize(500, 500);
    22. }
    23. MyMeter1::~MyMeter1()
    24. {
    25. }
    26. void MyMeter1::setValue(double val)
    27. {
    28. m_value = val;
    29. }
    30. //绘制表冠
    31. void MyMeter1::drawCrown(QPainter *painter)
    32. {
    33. painter->save();
    34. int radius = 100;
    35. QLinearGradient lg1(0, -radius, 0, radius);
    36. lg1.setColorAt(0, Qt::white); //设置渐变的颜色和路径比例
    37. lg1.setColorAt(1, Qt::gray); //只是粗略的颜色,具体的可以参考RGB颜色查询对照表
    38. painter->setBrush(lg1); // 创建QBrush对象,把这个渐变对象传递进去:
    39. painter->setPen(Qt::NoPen); //边框线无色
    40. painter->drawEllipse(-radius, -radius, radius << 1, radius << 1);
    41. painter->setBrush(m_background = Qt::black);
    42. painter->drawEllipse(-92, -92, 184, 184);
    43. painter->restore();
    44. }
    45. //绘制刻度数字
    46. void MyMeter1::drawScaleNum(QPainter *painter)
    47. {
    48. painter->save();
    49. painter->setPen(m_foreground);
    50. //m_startAngle是起始角度,m_endAngle是结束角度,m_scaleMajor在一个量程中分成的刻度数
    51. double startRad = ( 270-m_startAngle) * (3.14 / 180);
    52. double deltaRad = (360 - m_startAngle - m_endAngle) * (3.14 / 180) / m_scaleMajor;
    53. double sina,cosa;
    54. int x, y;
    55. QFontMetricsF fm(this->font());
    56. double w, h, tmpVal;
    57. QString str;
    58. for (int i = 0; i <= m_scaleMajor; i++)
    59. {
    60. sina = sin(startRad - i * deltaRad);
    61. cosa = cos(startRad - i * deltaRad);
    62. tmpVal = 1.0 * i *((m_maxValue - m_minValue) / m_scaleMajor) + m_minValue;
    63. // tmpVal = 50;
    64. str = QString( "%1" ).arg(tmpVal); //%1作为占位符 arg()函数比起 sprintf()来是类型安全的
    65. w = fm.size(Qt::TextSingleLine,str).width();
    66. h = fm.size(Qt::TextSingleLine,str).height();
    67. x = 82 * cosa - w / 2;
    68. y = -82 * sina + h / 4;
    69. painter->drawText(x, y, str); //函数的前两个参数是显示的坐标位置,后一个是显示的内容,是字符类型""
    70. }
    71. painter->restore();
    72. }
    73. // 绘制刻度线
    74. void MyMeter1::drawScale(QPainter *painter) //绘制刻度线
    75. {
    76. painter->save();
    77. painter->rotate(m_startAngle);
    78. int steps = (m_scaleMajor * m_scaleMinor); //相乘后的值是分的份数
    79. double angleStep = (360.0 - m_startAngle - m_endAngle) / steps; //每一个份数的角度
    80. // painter->setPen(m_foreground); //m_foreground是颜色的设置
    81. // QPen pen = painter->pen(); //第一种方法
    82. QPen pen ;
    83. pen.setColor(Qt::green); //推荐使用第二种方式
    84. for (int i = 0; i <= steps; i++)
    85. {
    86. if (i % m_scaleMinor == 0)//整数刻度显示加粗
    87. {
    88. pen.setWidth(1); //设置线宽
    89. painter->setPen(pen); //使用面向对象的思想,把画笔关联上画家。通过画家画出来
    90. painter->drawLine(0, 62, 0, 72); //两个参数应该是两个坐标值
    91. }
    92. else
    93. {
    94. pen.setWidth(0);
    95. painter->setPen(pen);
    96. painter->drawLine(0, 67, 0, 72);
    97. }
    98. painter->rotate(angleStep);
    99. }
    100. painter->restore();
    101. }
    102. void MyMeter1::drawTitle(QPainter *painter)
    103. {
    104. painter->save();
    105. painter->setPen(m_foreground);
    106. //painter->setBrush(m_foreground);
    107. QString str(m_title); //显示仪表的功能
    108. QFontMetricsF fm(this->font());
    109. double w = fm.size(Qt::TextSingleLine,str).width();
    110. painter->drawText(-w / 2, -30, str);
    111. painter->restore();
    112. }
    113. // 显示的单位,与数值
    114. void MyMeter1::drawNumericValue(QPainter *painter)
    115. {
    116. QString str = QString("%1 %2").arg(m_value, 0, 'f', m_precision).arg(m_units);
    117. QFontMetricsF fm(font());
    118. double w = fm.size(Qt::TextSingleLine,str).width();
    119. painter->setPen(m_foreground);
    120. painter->drawText(-w / 2, 42, str);
    121. }
    122. void MyMeter1::UpdateAngle()
    123. {
    124. update();
    125. }
    126. // 绘制表针,和中心点
    127. void MyMeter1::drawIndicator(QPainter *painter)
    128. {
    129. painter->save();
    130. QPolygon pts;
    131. pts.setPoints(3, -2, 0, 2, 0, 0, 60); /* (-2,0)/(2,0)/(0,60) *///第一个参数是 ,坐标的个数。后边的是坐标
    132. painter->rotate(m_startAngle);
    133. double degRotate = (360.0 - m_startAngle - m_endAngle) / (m_maxValue - m_minValue)*(m_value - m_minValue);
    134. //画指针
    135. painter->rotate(degRotate); //顺时针旋转坐标系统
    136. QRadialGradient haloGradient(0, 0, 60, 0, 0); //辐射渐变
    137. haloGradient.setColorAt(0, QColor(60, 60, 60));
    138. haloGradient.setColorAt(1, QColor(160, 160, 160)); //灰
    139. painter->setPen(Qt::white); //定义线条文本颜色 设置线条的颜色
    140. painter->setBrush(haloGradient);//刷子定义形状如何填满 填充后的颜色
    141. painter->drawConvexPolygon(pts); //这是个重载函数,绘制多边形。
    142. painter->restore();
    143. //画中心点
    144. QColor niceBlue(150, 150, 200);
    145. QConicalGradient coneGradient(0, 0, -90.0); //角度渐变
    146. coneGradient.setColorAt(0.0, Qt::darkGray);
    147. coneGradient.setColorAt(0.2, niceBlue);
    148. coneGradient.setColorAt(0.5, Qt::white);
    149. coneGradient.setColorAt(1.0, Qt::darkGray);
    150. painter->setPen(Qt::NoPen); //没有线,填满没有边界
    151. painter->setBrush(coneGradient);
    152. painter->drawEllipse(-5, -5, 10, 10);
    153. }
    154. // 重绘函数
    155. void MyMeter1 ::paintEvent(QPaintEvent *)
    156. {
    157. int width=this->width();
    158. int height=this->height();
    159. QPainter painter(this);//一个类中的this表示一个指向该类自己的指针
    160. painter.setRenderHint(QPainter::Antialiasing); /* 使用反锯齿(如果可用) */
    161. painter.translate(width/2, height/2); /* 坐标变换为窗体中心 */
    162. int side = qMin(width, height);
    163. painter.scale(side / 200.0, side / 200.0); /* 比例缩放 */
    164. drawCrown(&painter); /* 画表盘边框 */
    165. drawScaleNum(&painter); /* 画刻度数值值 */
    166. drawScale(&painter); /* 画刻度线 */
    167. drawTitle(&painter); /* 画单位 */
    168. drawNumericValue(&painter); /* 画数字显示 */
    169. drawIndicator(&painter); /* 画表针 */
    170. }
    171. void MyMeter1::mousePressEvent(QMouseEvent *event)
    172. {
    173. if( (event->button() == Qt::LeftButton) ){
    174. mouse_press = true;
    175. mousePoint = event->globalPos() - this->pos();
    176. // event->accept();
    177. }
    178. else if(event->button() == Qt::RightButton){
    179. //如果是右键
    180. this->close();
    181. }
    182. }
    183. void MyMeter1::mouseMoveEvent(QMouseEvent *event)
    184. {
    185. // if(event->buttons() == Qt::LeftButton){ //如果这里写这行代码,拖动会有点问题
    186. if(mouse_press){
    187. move(event->globalPos() - mousePoint);
    188. // event->accept();
    189. }
    190. }
    191. void MyMeter1::mouseReleaseEvent(QMouseEvent *event)
    192. {
    193. mouse_press = false;
    194. }

    meter2.cpp

    1. #include "meter2.h"
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. MyMeter2::MyMeter2(QWidget *parent)
    10. : QWidget(parent)
    11. {
    12. //resize(800, 480);
    13. //setWindowTitle("test");
    14. m_foreground = Qt::red;//Qt::black;
    15. speed = 0;
    16. status = 0;
    17. m_startAngle = 45;
    18. m_endAngle = 45;
    19. m_minValue = 0;
    20. m_maxValue = 100;
    21. m_scaleMajor = 10;//分度
    22. m_scaleMinor = 10;
    23. m_units = "KM/H";
    24. m_title = "My Speed";
    25. m_precision = 0;
    26. m_value = 0;
    27. m_angle = (qreal)270/(m_maxValue-1);
    28. //setWindowFlags(Qt::FramelessWindowHint);//无窗体
    29. //setAttribute(Qt::WA_TranslucentBackground);//背景透明
    30. time_id = this->startTimer(50);
    31. }
    32. MyMeter2::~MyMeter2()
    33. {
    34. }
    35. void MyMeter2::paintEvent(QPaintEvent *event)
    36. {
    37. int width=this->width();
    38. int height=this->height();
    39. QPainter painter(this);
    40. painter.translate(width/2, height/2);
    41. int side = qMin(width, height);
    42. painter.scale(side / 200.0, side / 200.0); /* 比例缩放 */
    43. drawFrame(&painter);
    44. drawScale(&painter); /* 画刻度线 */
    45. drawScaleNum(&painter); /* 画刻度数值值 */
    46. drawUnit(&painter);
    47. drawPointer(&painter);
    48. drawSpeed(&painter);
    49. }
    50. void MyMeter2::drawFrame(QPainter *painter)
    51. {
    52. painter->save();
    53. // 半径100
    54. int radius = 100;
    55. painter->setBrush(QBrush(QColor(0, 255, 0, 255), Qt::SolidPattern));
    56. painter->drawArc(-radius, -radius, radius<<1, radius<<1, -135*16, -270*16);
    57. painter->restore();
    58. }
    59. // 绘制刻度线
    60. void MyMeter2::drawScale(QPainter *painter)
    61. {
    62. painter->save();
    63. painter->rotate(m_startAngle);
    64. int steps = (m_scaleMajor * m_scaleMinor); //相乘后的值是分的份数
    65. double angleStep = (360.0 - m_startAngle - m_endAngle) / steps; //每一个份数的角度
    66. // painter->setPen(m_foreground); //m_foreground是颜色的设置
    67. // QPen pen = painter->pen(); //第一种方法
    68. QPen pen ;
    69. pen.setColor(m_foreground); //推荐使用第二种方式
    70. for (int i = 0; i <= steps; i++)
    71. {
    72. if (i % m_scaleMinor == 0)//整数刻度显示加粗
    73. {
    74. pen.setWidth(1); //设置线宽
    75. painter->setPen(pen); //使用面向对象的思想,把画笔关联上画家。通过画家画出来
    76. painter->drawLine(0, 90, 0, 100); //两个参数应该是两个坐标值
    77. }
    78. else
    79. {
    80. pen.setWidth(0);
    81. painter->setPen(pen);
    82. painter->drawLine(0, 95, 0, 100);
    83. }
    84. painter->rotate(angleStep);
    85. }
    86. painter->restore();
    87. }
    88. // 绘制刻度
    89. void MyMeter2::drawScaleNum(QPainter *painter)
    90. {
    91. painter->save();
    92. painter->setPen(m_foreground);
    93. //m_startAngle是起始角度,m_endAngle是结束角度,m_scaleMajor在一个量程中分成的刻度数
    94. double startRad = ( 270-m_startAngle) * (3.14 / 180);
    95. double deltaRad = (360 - m_startAngle - m_endAngle) * (3.14 / 180) / m_scaleMajor;
    96. double sina,cosa;
    97. int x, y;
    98. QFontMetricsF fm(this->font());
    99. double w, h, tmpVal;
    100. QString str;
    101. for (int i = 0; i <= m_scaleMajor; i++)
    102. {
    103. sina = sin(startRad - i * deltaRad);
    104. cosa = cos(startRad - i * deltaRad);
    105. tmpVal = 1.0 * i *((m_maxValue - m_minValue) / m_scaleMajor) + m_minValue;
    106. // tmpVal = 50;
    107. str = QString( "%1" ).arg(tmpVal); //%1作为占位符 arg()函数比起 sprintf()来是类型安全的
    108. w = fm.size(Qt::TextSingleLine,str).width();
    109. h = fm.size(Qt::TextSingleLine,str).height();
    110. x = 82 * cosa - w / 2;
    111. y = -82 * sina + h / 4;
    112. painter->drawText(x, y, str); //函数的前两个参数是显示的坐标位置,后一个是显示的内容,是字符类型""
    113. }
    114. painter->restore();
    115. }
    116. void MyMeter2::drawPointer(QPainter *painter)
    117. {
    118. int radius = 100;
    119. QPoint point[4] = {
    120. QPoint(0, 10),
    121. QPoint(-10, 0),
    122. QPoint(0, -80),
    123. QPoint(10, 0),
    124. };
    125. painter->save();
    126. QLinearGradient linear;
    127. linear.setStart(-radius, -radius);
    128. linear.setFinalStop(radius<<1, radius<<1);
    129. linear.setColorAt(0, QColor(0, 255, 255, 0));
    130. linear.setColorAt(1, QColor(0, 255, 255, 255));
    131. painter->setPen(Qt::NoPen);
    132. painter->setBrush(linear);
    133. painter->drawPie(-radius, -radius, radius<<1, radius<<1, 225 * 16, -(m_angle * this->speed) * 16);
    134. painter->restore();
    135. painter->save();
    136. painter->setBrush(QBrush(QColor(0, 0, 0, 255), Qt::SolidPattern));
    137. painter->rotate(-135 + this->speed * m_angle);
    138. painter->drawPolygon(point, 4);
    139. painter->restore();
    140. }
    141. void MyMeter2::drawSpeed(QPainter *painter)
    142. {
    143. painter->save();
    144. painter->setPen(QColor("#0"));
    145. // 绘制速度
    146. QFont font("Times", 10, QFont::Bold);
    147. font.setBold(true);
    148. font.setPixelSize(46);
    149. painter->setFont(font);
    150. painter->drawText(-60, 0, 120, 92, Qt::AlignCenter, QString::number(speed));
    151. painter->restore();
    152. }
    153. void MyMeter2::drawUnit(QPainter *painter)
    154. {
    155. QString str = QString("%1").arg(m_units);
    156. QFontMetricsF fm(font());
    157. double w = fm.size(Qt::TextSingleLine,str).width();
    158. painter->setPen(m_foreground);
    159. painter->drawText(-w / 2, 82, str);
    160. }
    161. void MyMeter2::timerEvent(QTimerEvent *e)
    162. {
    163. int timerId = e->timerId();
    164. if(this->time_id == timerId) {
    165. if(this->status == 0) {
    166. this->speed += 1;
    167. if(this->speed >= m_maxValue)
    168. this->status = 1;
    169. }else {
    170. this->speed -= 1;
    171. if(this->speed <= 0)
    172. this->status = 0;
    173. }
    174. this->update();
    175. }
    176. }

    main.cpp

    1. #include "mainwindow.h"
    2. #include "meter1.h"
    3. #include "meter2.h"
    4. #include "drawdialog.h"
    5. #include
    6. int main(int argc, char *argv[])
    7. {
    8. QApplication a(argc, argv);
    9. MyMeter1 w1;
    10. w1.setValue(33.12);
    11. w1.show();
    12. MyMeter2 w2;
    13. w2.show();
    14. DrawDialog w3;
    15. w3.show();
    16. return a.exec();
    17. }

  • 相关阅读:
    h0055. 长方体
    纯CSS实现禁止网页文本被选中
    依赖注入有几种实现方式?
    25.leetcode---只出现一次的数字(Java版)
    算法-堆/多路归并-查找和最小的 K 对数字
    Ubuntu下Qt creator不能输入中文解决方法
    大语言模型的关键技术
    Vuex入门
    ELK专栏之ES索引-04
    【MySQL】表的增删改查
  • 原文地址:https://blog.csdn.net/hsy12342611/article/details/133967375