文章目录
- 【1】eventFilter使用简介
- 【2】QPainter使用简介
- 【3】QPainter绘制温度案例
- 头文件
- 源文件
- 【4】 UI界面设计
- 【5】温度绘制图
【1】eventFilter使用简介
Qt的eventFilter
是一个事件过滤器,可以用来捕获和处理Qt对象的事件。事件过滤器可以被安装到一个对象上,以便在该对象上拦截和处理包含特定类型和内容的事件。下面是eventFilter
的简单使用介绍:
- 创建一个类,并继承自
QObject
。这个类将作为事件过滤器的实现。 - 在该类中,重写
eventFilter
函数。eventFilter
函数接收两个参数:QObject* watched
和QEvent* event
,用于捕获事件和处理事件。- 参数
watched
是事件发送方的指针,可以用来检查事件发送方的类型或属性。 - 参数
event
是要处理的事件对象,可以用于检查事件类型和内容,并采取相应的处理措施。
- 参数
- 在需要安装事件过滤器的Qt对象上调用
installEventFilter
函数,将事件过滤器实例添加到该对象。 - 在事件过滤器的
eventFilter
函数中,检查event
参数的事件类型,并处理感兴趣的事件。可以返回true
来指示事件被过滤,停止传递给目标对象;或返回false
以允许事件继续传递给目标对象。
下面是一个简单的示例,展示了如何使用eventFilter
:
#include <QObject>
#include <QEvent>
class MyEventFilter : public QObject
{
Q_OBJECT
public:
explicit MyEventFilter(QObject* parent = nullptr) : QObject(parent) {}
protected:
bool eventFilter(QObject* watched, QEvent* event) override
{
if (event->type() == QEvent::MouseButtonPress)
{
// 处理鼠标按下事件
// ...
return true; // 返回 true 表示事件已被过滤
}
else if (event->type() == QEvent::KeyPress)
{
// 处理键盘按下事件
// ...
return true; // 返回 true 表示事件已被过滤
}
return QObject::eventFilter(watched, event); // 其他事件传递给目标对象
}
};
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QWidget widget;
MyEventFilter filter;
widget.installEventFilter(&filter);
widget.show();
return app.exec();
}
以上示例中,MyEventFilter
类是一个事件过滤器,继承自QObject
类,并重写了eventFilter
函数。在main
函数中,创建一个QWidget
对象,并将MyEventFilter
对象实例filter
安装到该对象上,以便拦截和处理鼠标和键盘事件。
【2】QPainter使用简介
QPainter
是Qt框架中用于绘图的类,用于在Qt应用程序中进行2D图形渲染。它提供了一套用于绘制图形、绘制文本、设置画刷和画笔等功能的API。
以下是使用QPainter
进行绘图的基本步骤:
- 创建一个
QPainter
对象:在绘图之前,需要创建一个QPainter
对象,该对象将用于绘制。
QPainter painter(this); // 在窗口或自定义绘图设备上创建QPainter对象
- 设置绘图参数:可以通过设置画刷(
QBrush
)和画笔(QPen
)来指定绘图的样式和属性。
QBrush brush(Qt::red); // 创建一个画刷对象,设置颜色为红色
QPen pen(Qt::blue); // 创建一个画笔对象,设置颜色为蓝色
painter.setBrush(brush); // 将画刷对象设置给绘图设备
painter.setPen(pen); // 将画笔对象设置给绘图设备
- 绘制图形:使用
QPainter
对象提供的绘图函数绘制所需的图形。
painter.drawRect(20, 20, 100, 100); // 绘制矩形
painter.drawEllipse(50, 50, 100, 100); // 绘制椭圆
- 绘制文本:使用
QPainter
对象的绘制文本函数绘制所需的文本。
painter.drawText(20, 150, "Hello Qt!"); // 绘制文本
- 结束绘图:完成绘图后,需要结束绘图操作。
painter.end(); // 结束绘图操作
以上是QPainter
的基本使用方法。使用QPainter
可以绘制各种图形,以及在窗口或自定义绘图设备上进行自定义绘图。还可以使用QPainter
绘制图像、渐变等更高级的绘图操作。
【3】QPainter绘制温度案例
头文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QDebug>
#include <QRandomGenerator64> //生成随机数
#include <QPainter>
// 温度曲线相关的宏
#define PADDING 50
#define INCREMENT 8 // 温度曲线像素增量
#define POINT_RADIUS 3 // 曲线描点的大小
#define TEXT_OFFSET_X 12 // 温度文本相对于点的偏移
#define TEXT_OFFSET_Y 10 // 温度文本相对于点的偏移
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void paintHigh();
void paintLow();
protected:
bool eventFilter(QObject*watched, QEvent*event) override;
private:
Ui::Widget *ui;
// 自定义变量
int highTemp[7] = {0};
int lowTemp[7] = {0};
void updateTemp();
};
#endif // WIDGET_H
源文件
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
updateTemp();
ui->label_high->installEventFilter(this);
ui->label_low->installEventFilter(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintHigh()
{
QPainter painter(ui->label_high);
painter.setRenderHint(QPainter::Antialiasing, true); // 抗锯齿
// 1. 计算 x 轴坐标
int pointX[7] = {0};
qDebug()<<"ui->label_high->pos().x() = "<<ui->label_high->pos().x();
qDebug()<<"ui->label_high->width() = "<<ui->label_high->width();
for ( int i = 0; i < 7; i++ ) {
pointX[i] = ui->label_high->pos().x() + PADDING + (ui->label_high->width() - PADDING * 2) / 6 * i;
qDebug()<<"pointX[" <<i<<"] = "<<pointX[i];
}
// 2. 计算 y 轴坐标
// 2.1 计算平均值
int tempSum = 0;
int tempAverage = 0;
for ( int i = 0; i < 7; i++ ) {
tempSum += highTemp[i];
}
tempAverage = tempSum / 7; // 最高温平均值
qDebug()<<"tempAverage = "<<tempAverage;
// 2.2 计算 y 轴坐标
int pointY[7] = {0};
int yCenter = ui->label_high->height() / 2;
int increment = ui->label_high->height() / 20;
qDebug()<<"ui->label_high->height() = "<<ui->label_high->height();
qDebug()<<"yCenter = "<<yCenter;
qDebug()<<"increment = "<<increment;
for ( int i = 0; i < 7; i++ ) {
pointY[i] = yCenter - ((highTemp[i] - tempAverage) * increment);
qDebug()<<"pointY[" <<i<<"] = "<<pointY[i];
}
qDebug() <<endl;
// 3. 开始绘制
// 3.1 初始化画笔
QPen pen = painter.pen();
pen.setWidth(1); //设置画笔宽度为1
pen.setColor(QColor(255, 170, 0)); //设置颜色
painter.setPen(pen);
painter.setBrush(QColor(255, 170, 0)); //设置画刷颜色
painter.setFont(QFont("Microsoft YaHei", 14));
// 3.2 画点、写文本
for ( int i = 0; i < 7; i++ ) {
painter.drawEllipse(QPoint(pointX[i], pointY[i]), POINT_RADIUS, POINT_RADIUS); // 画点
painter.drawText(QPoint(pointX[i] - TEXT_OFFSET_X, pointY[i] - TEXT_OFFSET_Y), QString::number(highTemp[i]) + " ℃"); // 画文本
}
// 3.3 绘制曲线
for ( int i = 0; i < 6; i++ ) { // 循环控制6次
if ( i == 0 ) {
pen.setStyle(Qt::DotLine); // 虚线
painter.setPen(pen);
} else {
pen.setStyle(Qt::SolidLine); // 实线
painter.setPen(pen);
}
painter.drawLine(pointX[i], pointY[i], pointX[i + 1], pointY[i + 1]); // 两点确定一条直线
}
}
void Widget::paintLow()
{
QPainter painter(ui->label_low);
painter.setRenderHint(QPainter::Antialiasing, true); // 抗锯齿
// 1. 计算 x 轴坐标
int pointX[7] = {0};
for ( int i = 0; i < 7; i++ ) {
pointX[i] = ui->label_low->pos().x() + PADDING + (ui->label_low->width() - PADDING * 2) / 6 * i;
}
// 2. 计算 y 轴坐标
// 2.1 计算平均值
int tempSum = 0;
int tempAverage = 0;
for ( int i = 0; i < 7; i++ ) {
tempSum += lowTemp[i];
}
tempAverage = tempSum / 7; // 最高温平均值
// 2.2 计算 y 轴坐标
int pointY[7] = {0};
int yCenter = ui->label_low->height() / 2;
int increment = ui->label_low->height() / 20;
for ( int i = 0; i < 7; i++ ) {
pointY[i] = yCenter - ((lowTemp[i] - tempAverage) * increment);
}
// 3. 开始绘制
// 3.1 初始化画笔
QPen pen = painter.pen();
pen.setWidth(1); // 设置画笔宽度为1
pen.setColor(QColor(0, 255, 255)); // 设置颜色
painter.setPen(pen);
painter.setBrush(QColor(0, 255, 255)); //设置画刷颜色
painter.setFont(QFont("Microsoft YaHei", 14));
// 3.2 画点、写文本
for ( int i = 0; i < 7; i++ ) {
painter.drawEllipse(QPoint(pointX[i], pointY[i]), POINT_RADIUS, POINT_RADIUS);
painter.drawText(QPoint(pointX[i] - TEXT_OFFSET_X, pointY[i] - TEXT_OFFSET_Y), QString::number(lowTemp[i]) + " ℃");
}
// 3.3 绘制曲线
for ( int i = 0; i < 6; i++ ) {
if ( i == 0 ) {
pen.setStyle(Qt::DotLine); //虚线
painter.setPen(pen);
} else {
pen.setStyle(Qt::SolidLine); // 实线
painter.setPen(pen);
}
painter.drawLine(pointX[i], pointY[i], pointX[i + 1], pointY[i + 1]);
}
}
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::Paint) {
if (watched == ui->label_high) {
this->paintHigh();
}
if (watched == ui->label_low) {
this->paintLow();
}
}
else if (event->type() == QEvent::MouseButtonDblClick) {
this->updateTemp();
}
return QWidget::eventFilter(watched,event); // 未处理返回false
}
void Widget::updateTemp()
{
for (int i = 0; i<7;i++) {
highTemp[i] = 20 + QRandomGenerator::global()->generate() % 10;
lowTemp[i] = -5 + QRandomGenerator::global()->generate() % 10;
}
ui->label_low->update();
ui->label_high->update();
}
【4】 UI界面设计
【5】温度绘制图
通过双击组件可以更新温度