学习QT之自定义控件入门学习#-仪表盘


由于本人目前也是在入门学习,此实例是学习了 BiLiBiLi up主:xieguimsn的视频教程,十分的感谢!写本文章的目的一来是理清一下学习思路和一些自己的理解,二来是方便以后自己查看。 原创作者视频教程中有源代码的下载方式,希望大家多多支持原创

一、绘制过程详解

Qt绘图是通过重写paintEvent(QPaintEvent *event)来实现的,调用这个函数有两种方式:update()repaint(),对绘图原理不清楚的同学,可以去翻看我的前一篇文章:Qt绘图原理详解。为了实时调用update()函数以实时调用绘制事件函数,我们定义一个定时器,定时刷新界面。绘制的步骤分以下几步:

1、窗体绘制准备

我们都知道,Qt的窗体是方形的,但是我们最终的仪表盘肯定是圆形的,所以在绘制之前我们要将窗体整个设置为透明,然后我们再在上面绘制,看起来的效果就好像控件窗体是圆形的了,其实它还是方形的。

2、绘制表盘

在这里插入图片描述

我们可以把表盘拆解一下,此处有两种拆解方案:

  1. 先画最外层的圆并填充为灰色,再画中间的圆(刻度盘)并填充为黑色,最后画内层的圆也填充为灰色,之后再补上中心区域的红色小圆。

  2. 先画最外层的圆并填充为灰色,然后再画一个黑色圆环,最后补上中心区域的红色小圆。

在这里我们采用方案1,因为这种方案较为简单。

3、绘制刻度

在这里插入图片描述

首先我们需要确定我们绘制刻度的区域是在哪一块,我们设置基础角度为135°,若以圆心所在竖线为0°参考点,左右各为135°,所以总共有270°,也就是下图大扇形区域内的黑环中。(实际绘图是以圆心所在横线右侧为0°)

在这里插入图片描述

我们在刻度盘中画10个大刻度,每个大刻度里画5个小刻度,所以总共有5*10=50个刻度,每个刻度的所占度数为:270° / (5 * 10)=5.4°。然后我们现在就知道了每个刻度的角度,例如第一个刻度的角度为135度,第二个刻度的角度为140.4°;

刻度无非就是直线,为了画出直线,我们必须知道直线的起点和终点。对于起点而言(刻度线的外端点),它的半径是固定的,即黑色圆的半径;对于终点而言(刻度线的内端点),它的半径是不固定的,大刻度线比较长,小刻度线比较短,大刻度线对应的半径为内层圆的半径(黑色圆环的内侧到圆心的距离),小刻度线对应的半径为内层圆的半径往外偏移一些(大于黑色圆环的内侧到圆心的距离)。

现在我们知道了每个刻度线对应的角度和半径,我们就可以求出每条刻度线的起点和终点了,公式如下:

int x = 圆心的横坐标 + 半径 * cos(角度 * π / 180);
int y = 圆心的纵坐标 + 半径 * sin(角度 * π / 180);

在这里插入图片描述

4、绘制文字

在这里插入图片描述

我们需要绘制的有两部分:第一部分实时的数值,第二部分是刻度对应的数值。我们只绘制大刻度的数值,可以参考绘制刻度中采用的方法确定待绘制刻度值的坐标,然后绘制一个正方体,在其中填入要绘制的刻度值(字符类型)。

5、绘制指针

在这里插入图片描述
指针我们把它拆分为两部分:第一部分为一个三角形;第二部分为一个同色的圆。画三角形需要确定三个点,最外部那个点的半径是最内层圆的半径,内部那两个点的半径是相同的,只需要满足它们的半径小于同色的圆的半径即可。

二、运行原理详解

由于我们的绘制事件函数采用定时器定时执行,所以我们只需要改变当前的值,在其重绘指针时就会根据当前的值重写计算并绘制指针,所以看起来的效果就是我们改变当前的值指针就会移动。

旋转仪表盘是一种常见的显示控件,可以用来展示一些数据,如速度、油量、温度等,下面我将介绍如何使用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布局中,并设置为主窗口的中央控件。 至此,我们已经完成了一个简单的旋转仪表盘自定义控件。你可以根据需要对其进行扩展和优化,使其更加适合你的应用场景。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贝勒里恩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值