文章目录
简述:
本篇主要叙述Qt中的事件系统,在实际开发工程中所用到的经验。
如果对Qt事件理论知识不懂,访问https://blog.csdn.net/QQ1402369668/article/details/104224896
最简单/直接的事件处理
mousePressEvent()
void Widget::mousePressEvent(QMouseEvent *e)
{
if(Qt::LeftButton == e->button()){
qDebug()<<"mousePressEvent() Left";
}
else if (Qt::RightButton == e->button()) {
qDebug()<<"mousePressEvent() Right";
}
else {
}
}
paintEvent()
void Widget::paintEvent(QPaintEvent *event)
{
//背景半透明
QPainter p;
p.begin(this);
p.fillRect(rect(), QColor(0,0,0,127));
p.end();
}
事件过滤器
注意:以下这种情况
情形1:
ui->pushButton->installEventFilter(this);
bool Widget::eventFilter(QObject *obj, QEvent *event)
{
if(obj == ui->pushButton){
if(event->type() == QEvent::MouseButtonPress){
qDebug()<<"eventFilter() ui->pushButton MouseButtonPress";
return false;
}
}
return QObject::eventFilter(obj, event); //其他的默认调用父类的方法
}
void Widget::on_pushButton_clicked()
{
qDebug()<<"on_pushButton_clicked()";
}
情形2:
ui->pushButton->installEventFilter(this);
bool Widget::eventFilter(QObject *obj, QEvent *event)
{
if(obj == ui->pushButton){
if(event->type() == QEvent::MouseButtonPress){
qDebug()<<"eventFilter() ui->pushButton MouseButtonPress";
return true; //修改了此处
}
}
return QObject::eventFilter(obj, event); //其他的默认调用父类的方法
}
void Widget::on_pushButton_clicked()
{
qDebug()<<"on_pushButton_clicked()";
}
这两种情况比较:
事件先经过事件过滤器,再经过槽函数;
事件过滤器返回false, 会继续传播到槽函数;
事件过滤器返回true,不会继续,槽函数不会执行;
自定义事件:
为什么要自定义事件
1.信号槽是一对一的,当要在多个地方响应同一个信号的时候,使用信号槽会显得臃肿。
实现
首先自定义事件类
CustomEvent.h
#ifndef CUSTOMEVENT_H
#define CUSTOMEVENT_H
#include <QObject>
#include <QEvent>
#include <QVariant>
//事件类型
enum ECustomEventType{
ETest1 = QEvent::User + 1,
ETest2,
};
class CustomEvent : public QEvent
{
public:
/**
* 概述:
* 参数:QEvent的类型,自定义参数...
* 返回值:
*/
explicit CustomEvent(ECustomEventType type,
QVariant par1 = QVariant(),
QVariant par2 = QVariant(),
QVariant par3 = QVariant(),
QVariant par4 = QVariant(),
QVariant par5 = QVariant(),
QVariant par6 = QVariant(),
QVariant par7 = QVariant()
);
private:
QVariant m_par1;
QVariant m_par2;
QVariant m_par3;
QVariant m_par4;
QVariant m_par5;
QVariant m_par6;
QVariant m_par7;
friend class Widget;
};
#endif // CUSTOMEVENT_H
CustomEvent.cpp
#include "customevent.h"
CustomEvent::CustomEvent(ECustomEventType type,
QVariant par1,
QVariant par2,
QVariant par3,
QVariant par4,
QVariant par5,
QVariant par6,
QVariant par7
)
: QEvent(Type(type) ),
m_par1(par1),
m_par2(par2),
m_par3(par3),
m_par4(par4),
m_par5(par5),
m_par6(par6),
m_par7(par7)
{
}
Widget.cpp
//自定义事件
//发送事件
void Widget::postEventToObj(ECustomEventType eType,
QVariant par1, QVariant par2)
{
CustomEvent* pEvent = new CustomEvent(eType,
par1, par2
);
QCoreApplication::postEvent(this, pEvent); //注意:post方式event必须在堆上分配
}
//接收事件
bool Widget::event(QEvent *ev)
{
switch (ECustomEventType(ev->type()) ) {
case ETest1: //ETest1
{
CustomEvent *pCustomEvent = dynamic_cast<CustomEvent*>(ev);
qDebug()<<"ETest1"<< pCustomEvent->m_par1<<pCustomEvent->m_par2;
return true;
}
break;
case ETest2: //ETest2
{
CustomEvent *pCustomEvent = dynamic_cast<CustomEvent*>(ev);
qDebug()<< "ETest2"<<pCustomEvent->m_par1<<pCustomEvent->m_par1;
return true;
}
break;
default:
break;
}
return QWidget::event(ev); //调用默认父类函数
}
调用:
postEventToObj(ETest1, 111,222);
postEventToObj(ETest2, 333,444);
事件循环
事件循环QEventLoop 网络http请求
//http get请求
void Widget::httpGet()
{
// URL
QString baseUrl = "http://www.csdn.net/";
// 构造请求
QNetworkRequest request;
request.setUrl(QUrl(baseUrl));
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
// 发送请求
QNetworkReply *pReplay = manager->get(request);
// 开启一个局部的事件循环,等待响应结束,退出
QEventLoop eventLoop;
QObject::connect(manager, &QNetworkAccessManager::finished, &eventLoop, &QEventLoop::quit);
eventLoop.exec();
// 获取响应信息
QByteArray bytes = pReplay->readAll();
qDebug() << bytes;
}
因为请求的过程是异步的,所以此时使用 QEventLoop 开启一个局部的事件循环,等待响应结束,事件循环退出。
**注意:**开启事件循环的同时,程序界面将不会响应用户操作(界面被阻塞)。
QApplication::processEvents()处理密集操作界面响应
在使用Qt的过程中,经常会碰到需要运行耗时的逻辑代码的时候,一般都采用多线程进行处理,这样可以保证主线程(界面)不会被占用,导致用户操作无效,出现等待无响应现象。
Qt本身提供一个函数QApplication::processEvents()来处理。
//processEvents()处理密集操作界面响应
void Widget::on_pushButton_4_clicked()
{
QDateTime time = QDateTime::currentDateTime();
time = time.addSecs(20);
while(1)
{
// QApplication::processEvents(QEventLoop::ExcludeUserInputEvents,20);
if(QDateTime::currentDateTime() > time)
return;
}
}
运行后,我们一直点界面,就会出现如下情形,界面卡死状态;
如何解决哪?
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents,20);
放开即可