在现代应用程序中,仪表盘是一种直观的方式,用于展示各种数据。使用 Qt 创建自定义控件,可以帮助我们绘制出功能强大且美观的仪表盘。本篇博文将带你深入理解如何通过具体的代码示例,实现一个类似于汽车速度表的仪表盘。
基于QT的仪表盘有很多种办法,比如使用QWT,ChartDirector 或H5混合的echart组件,或者基于QT的绘图功能绘制,或者基于美工提供的图片的基础上增加动态效果。然而搞明白QT自定义控件的绘图后,自定义绘图这种,实现是最简单最轻量级的。且定制度高,想要什么效果就可以自己绘制个。
所谓一通百通,有了以下示例的参考实现,任意实现一个类似的仪表盘,也是很简单的事情了。以下四个完整示例,是我们将要讨论的关键点。
工程demo源码下载:https://download.youkuaiyun.com/download/qq8864/90047925
初始化
在 MySpeed
类的构造函数中,我们设置了一些基本的属性,包括:
- 背景颜色和前景颜色:定义了仪表盘的背景和前景颜色。
- 速度值:用于模拟的当前速度,范围从 0 到 100。
- 单位和标题:定义了仪表盘显示的单位(湿度/%RH)和标题。
- 角度和刻度:定义了起始和结束角度以及刻度线的数量。
m_background = QColor(50, 154, 255, 200);
m_foreground = Qt::white;
speed = 0;
status = 0;
m_startAngle = 45;
m_endAngle = 45;
m_minValue = 0;
m_maxValue = 100;
m_scaleMajor = 10; // 分度
m_scaleMinor = 10;
m_units = "湿度/%RH";
m_title = "";
m_precision = 2;
m_value = 0;
m_angle = (qreal)270/(m_maxValue-1);
time_id = this->startTimer(50);
绘制事件
我们重写了 paintEvent
方法,在其中使用 QPainter
绘制仪表盘。
void MySpeed::paintEvent(QPaintEvent *event)
{
int width = this->width();
int height = this->height();
QPainter painter(this);
painter.translate(width / 2, height / 2); // 将原点移动到控件中心
int side = qMin(width, height);
painter.scale(side / 200.0, side / 200.0); // 等比缩放
drawFrame(&painter); // 绘制仪表盘框架
drawScale(&painter); // 绘制刻度线
drawScaleNum(&painter); // 绘制刻度数字
drawUnit(&painter); // 绘制单位
drawPointer(&painter); // 绘制指针
drawSpeed(&painter); // 绘制当前速度
}
绘制仪表盘框架
drawFrame
方法绘制了仪表盘的背景和形状。我们使用 QLinearGradient
创建一个渐变效果。
void MySpeed::drawFrame(QPainter *painter)
{
painter->save();
int radius = 100;
QLinearGradient lg1(0, -radius, 0, radius);
lg1.setColorAt(0, Qt::white);
lg1.setColorAt(1, Qt::gray);
painter->setBrush(lg1);
painter->setPen(Qt::NoPen);
painter->drawEllipse(-radius, -radius, radius << 1, radius << 1);
painter->setBrush(m_background);
painter->drawEllipse(-92, -92, 184, 184);
painter->restore();
}
绘制刻度和数字
在 drawScale
和 drawScaleNum
方法中,分别绘制了刻度线和刻度数字。使用三角函数确保刻度正确位置。
void MySpeed::drawScale(QPainter *painter)
{
painter->save();
painter->rotate(m_startAngle);
int steps = (m_scaleMajor * m_scaleMinor);
double angleStep = (360.0 - m_startAngle - m_endAngle) / steps;
for (int i = 0; i <= steps; i++)
{
if (i % m_scaleMinor == 0)
painter->drawLine(0, 90, 0, 98); // 主要刻度
else
painter->drawLine(0, 95, 0, 98); // 次要刻度
painter->rotate(angleStep);
}
painter->restore();
}
绘制指针和速度
drawPointer
方法负责绘制指针,使用渐变来增加视觉效果。drawSpeed
方法则绘制当前的速度值。
void MySpeed::drawPointer(QPainter *painter)
{
int radius = 100;
QPoint point[4] = {
QPoint(0, 10),
QPoint(-10, 0),
QPoint(0, -80),
QPoint(10, 0),
};
painter->save();
// 绘制指针的逻辑...
painter->restore();
}
void MySpeed::drawSpeed(QPainter *painter)
{
painter->save();
painter->setPen(Qt::white);
QFont font("Times", 10, QFont::Bold);
font.setBold(true);
font.setPixelSize(42);
painter->setFont(font);
painter->drawText(-60, 0, 120, 92, Qt::AlignCenter, QString::number(speed));
painter->restore();
}
连接定时器和动态效果
通过 timerEvent
方法,我们可以动态改变速度值以模拟速度表的运动。定时器每 50 毫秒触发一次,更新当前速度并重绘仪表盘。
void MySpeed::timerEvent(QTimerEvent *e)
{
// 动态变化速度
}
总结
通过以上的代码示例,我们成功实现了一个基本的仪表盘控件。掌握了这一实现方法后,您可以根据需要扩展仪表的功能,并为其他类型的仪表创建类似的绘制逻辑。Qt 的强大绘图能力和自定义控件机制,使我们能够轻松实现丰富多彩的用户界面。希望这些示例能为您设计其他仪表盘提供灵感和帮助!