• Qt编写自定义控件:圆形/半圆形仪表盘


    1. #include "widget.h"
    2. #include
    3. #include
    4. #include
    5. #include
    6. QRect getEllipseRect(const QPoint ¢er, int rx, int ry)
    7. {
    8. return QRect(center.x() - rx, center.y() - ry, 2 * rx, 2 * ry);
    9. }
    10. struct Graphical_DashboardPrivate
    11. {
    12. int maximumValue{100};
    13. int maximumScaleValue{280};
    14. int startAngle;
    15. int endAngle;
    16. bool semiCircle{0};//是否半圆
    17. QColor backgroundColor{"#ff000000"};
    18. QColor borderGradient_topLeftColor{"#ffffffff"};
    19. QColor borderGradient_bottomRightColor{"#ff000000"};
    20. QColor scaleColor{"#ffffffff"};
    21. QColor scaleValueColor{"#ffffffff"};
    22. QColor pointerBorderColor{"#ffffffff"};
    23. QColor pointerbackgroundColor{"#ffA0A0A0"};
    24. QColor centralWheelGradient_insideColor{"#ff808080"};
    25. QColor centralWheelGradient_outsideColor{"#ffffffff"};
    26. int pointerBorderWidth{3};
    27. int centralWheelRadius{26};
    28. qreal anglePerVel;
    29. void calculateClockwiseRange();
    30. void drawFrame(QPainter &painter);
    31. void drawScale(QPainter &painter);
    32. void drawScaleReadings(QPainter &painter);
    33. void drawPointer(QPainter &painter);
    34. };
    35. void Graphical_DashboardPrivate::calculateClockwiseRange()
    36. {
    37. if(maximumScaleValue >= 180)
    38. {
    39. startAngle = (360 - maximumScaleValue) / 2 + 90; // 计算起始角度,转换为顺时针角度
    40. endAngle = (startAngle + maximumScaleValue) % 360; // 计算结束角度,转换为顺时针角度
    41. anglePerVel = (360.0 - (startAngle - endAngle)) / maximumScaleValue;
    42. }
    43. else
    44. {
    45. startAngle = 270 - (maximumScaleValue/2);
    46. endAngle = startAngle + maximumScaleValue;
    47. anglePerVel = (endAngle - startAngle) / maximumScaleValue;
    48. }
    49. }
    50. //边框
    51. void Graphical_DashboardPrivate::drawFrame(QPainter &painter)
    52. {
    53. //500 = radius
    54. static QPoint origin{0,0};
    55. painter.save();
    56. painter.setPen(Qt::transparent);
    57. QLinearGradient lg(-500,-500,500,500);
    58. lg.setColorAt(0,borderGradient_topLeftColor);
    59. lg.setColorAt(1,borderGradient_bottomRightColor);
    60. painter.setBrush(lg);
    61. if(semiCircle)
    62. {
    63. auto rect = getEllipseRect(origin,500,500);
    64. int newHeight = rect.height() / 2;
    65. rect.setHeight(newHeight + 50);
    66. painter.setClipRect(rect);
    67. }
    68. painter.drawEllipse(origin,480,480);
    69. auto rect = getEllipseRect(origin,430,430);
    70. QPainterPath path;
    71. path.addEllipse(rect);
    72. painter.setClipPath(path);
    73. if(semiCircle)
    74. {
    75. int newHeight = rect.height() / 2;
    76. rect.setHeight(newHeight+12);
    77. }
    78. painter.fillRect(rect,backgroundColor);
    79. painter.restore();
    80. }
    81. //刻度
    82. void Graphical_DashboardPrivate::drawScale(QPainter &painter)
    83. {
    84. painter.save();
    85. painter.rotate(startAngle);//将坐标系顺时针旋转150°,到达起始位置
    86. int step = maximumScaleValue / 5;
    87. float angleStep;
    88. if(maximumScaleValue >= 180)
    89. {
    90. angleStep = (360.0 - (startAngle - endAngle)) / step;
    91. }
    92. else
    93. {
    94. angleStep = (endAngle - startAngle) / step;
    95. }
    96. for (int i = 0; i <= maximumScaleValue; i += 5)
    97. {
    98. if (i % 20 == 0)//粗线
    99. {
    100. painter.setPen(QPen(scaleColor,10));
    101. painter.drawLine(420, 0, 340, 0);
    102. }
    103. else if (i % 10 == 0)//中等
    104. {
    105. painter.setPen(QPen(scaleColor,6));
    106. painter.drawLine(420, 0, 380, 0);
    107. }
    108. else if (i % 5 == 0)//短线
    109. {
    110. painter.setPen(QPen(scaleColor,4));
    111. painter.drawLine(400, 0, 380, 0);
    112. }
    113. painter.rotate(angleStep);
    114. }
    115. painter.restore();
    116. }
    117. //刻度值
    118. void Graphical_DashboardPrivate::drawScaleReadings(QPainter &painter)
    119. {
    120. painter.save();
    121. painter.setPen(scaleValueColor);
    122. qreal x,y,w,h,angle,angleArc;
    123. auto font = painter.font();
    124. font.setPixelSize(45);
    125. painter.setFont(font);
    126. QFontMetricsF fm(font);
    127. for (int i = 0; i <= maximumScaleValue; i+= 20)
    128. {
    129. if (i % 20 == 0)
    130. {
    131. angle = 360 - (startAngle + i * anglePerVel); //角度
    132. angleArc = angle * 3.14 / 180; //转换为弧度
    133. x = 280 * cos(angleArc);
    134. y = -280 * sin(angleArc); // 负号的意义在于 Y轴正方向向下
    135. QString speed = QString::number(i * maximumValue/maximumScaleValue);
    136. w = fm.width(speed);
    137. h = fm.height();
    138. painter.drawText(QPointF(x - w / 2,y + h/4),speed);
    139. }
    140. }
    141. painter.restore();
    142. }
    143. //绘制指针
    144. void Graphical_DashboardPrivate::drawPointer(QPainter &painter)
    145. {
    146. painter.save();
    147. int currentValue = maximumScaleValue/2;
    148. float curAngle = startAngle + currentValue * anglePerVel;
    149. painter.rotate(curAngle); //旋转坐标系
    150. QRadialGradient haloGradient(0, 0, 60, 0, 0); //辐射渐变
    151. haloGradient.setColorAt(0, pointerbackgroundColor.darker());
    152. haloGradient.setColorAt(1, pointerbackgroundColor);
    153. if(pointerBorderWidth == 0)
    154. {
    155. painter.setPen(Qt::transparent);
    156. }
    157. else
    158. {
    159. painter.setPen(QPen(pointerBorderColor,pointerBorderWidth));
    160. }
    161. painter.setBrush(haloGradient);
    162. const QPointF points[3]
    163. {
    164. QPointF(0.0, centralWheelRadius/2),
    165. QPointF(0.0, -centralWheelRadius/2),
    166. QPointF(300.0, 0),
    167. };
    168. painter.drawPolygon(points,3); //绘制指针
    169. painter.restore();
    170. painter.save();
    171. //绘制旋转中心
    172. QRadialGradient rg(0,0,40);
    173. rg.setColorAt(0.0,centralWheelGradient_insideColor);
    174. rg.setColorAt(0.5,centralWheelGradient_outsideColor);
    175. rg.setColorAt(1.0,centralWheelGradient_insideColor);
    176. painter.setPen(Qt::NoPen);
    177. painter.setBrush(rg);
    178. painter.drawEllipse(QPoint(0,0),centralWheelRadius,centralWheelRadius);
    179. painter.restore();
    180. }
    181. Widget::Widget(QWidget *parent)
    182. : QWidget(parent)
    183. {
    184. setPalette(QPalette(QPalette::Background,Qt::white));
    185. d_ptr = new Graphical_DashboardPrivate;
    186. d_ptr->calculateClockwiseRange();
    187. }
    188. Widget::~Widget()
    189. {
    190. }
    191. void Widget::paintEvent(QPaintEvent *event)
    192. {
    193. auto thisRect = rect();
    194. QPainter painter(this);
    195. painter.setRenderHint(QPainter::Antialiasing);
    196. painter.setRenderHints(QPainter::TextAntialiasing);
    197. painter.setRenderHints(QPainter::SmoothPixmapTransform);
    198. int side;
    199. if(d_ptr->semiCircle)
    200. {
    201. side = qMin(thisRect.width(), thisRect.height()*2);
    202. side = qMin(thisRect.width(), thisRect.height()*2 - (side/20) * 2);
    203. painter.translate(thisRect.width() / 2, thisRect.height() - side /20 );
    204. }
    205. else
    206. {
    207. side = qMin(thisRect.width(), thisRect.height());
    208. painter.translate(thisRect.width() / 2, thisRect.height() / 2);
    209. }
    210. painter.scale(side / 1000.0, side / 1000.0);
    211. d_ptr->drawFrame(painter);
    212. d_ptr->drawScale(painter);
    213. d_ptr->drawScaleReadings(painter);
    214. d_ptr->drawPointer(painter);
    215. }

  • 相关阅读:
    SAR信号处理基础1——线性调频信号
    【AWS实验】 使用 Lake Formation 设置数据湖
    postgresql用户与权限管理
    Redis—听说你速度跟甲斗一样快?——哨兵
    基于JavaSwing开发推箱子小游戏(不同版) 课程设计 大作业源码
    前端集成钉钉自定义机器人消息
    ROS2中的行为树 BehaviorTree
    基于遗传优化的货柜货物摆放优化问题求解matlab仿真
    因为一次bug的教训,我决定手撕Nacos源码(先撕客户端源码)
    git 修改和补充本地的commit信息的操作
  • 原文地址:https://blog.csdn.net/kenfan1647/article/details/134512158