17.QT-事件处理分析、事件过滤器、拖放事件
Qt事件处理介绍
- Qt平台会将系统产生的消息转换为Qt事件
- Qt事件是一个QEvent的对象
- Qt事件用来描述程序内部或外部发生的动作
- 任意的QObject对象都具备事件处理的能力
Qt常见的事件继承图如下:

- QInputEvent:用户输入事件
- QDropEvent:用户拖放事件
- QPaintEvent:描述操作系统绘制GUI动作的事件
- QCloseEvent:用户关闭窗口事件
- QTimerEvent:计时器事件
事件处理方式顺序
1.Qt事件产生后立即被分发到QWidget对象
2.QWidget中的event(QEvent*)进行事件处理
3.event()根据事件类型调用不同的事件处理函数
4.在事件处理函数中发送Qt中预定义的信号
5.调用信号关联的槽函数
以按钮点击为例,如下图所示:

QPushButton事件处理总结
1.当点击按钮后,将会触发鼠标事件
2.调用event(QEvent*)成员函数
3.调用mouseReleaseEvent(QMouseEvent*)成员函数
4.调用click()成员函数
5.触发信号SIGNAL(clicked());
同样,当用户点击窗口的关闭按钮时,也会触发closeEvent()事件函数,该函数需要重写,才能实现
参考示例:
void MainWindow::closeEvent(QCloseEvent *event)
{
if (maybeSave()) //如果还有需要保存的数据
{
writeSettings();
event->accept();
}
else //取消关闭窗口
{
event->ignore();
}
}
类似的还有keyEvent()获取键盘事件函数, keyReleaseEvent()键盘按下事件函数,enterEvent光标进入组件事件函数, leaveEvent光标离开组件事件函数等等。
其中QCloseEvent继承与QEvent,在QEvent中常用成员函数有
void accept (); //接收者处理当前事件 void ignore (); //接收者忽略当前事件,忽略后,事件可能传递给父组件 bool isAccepted(); //判断当前事件是否被处理过
当使用ignore()处理事件时,该事件可能会传递给其父组件对象继续处理
步骤如下:
- 写两个类: QMyWidget、QMyLineEdit(QMyLineEdit是QMyWidget的类成员)
- 通过QMyLineEdit来重写LineEdit的keyReleaseEvent()键盘按下事件函数
- 通过QMyWidget来重写QWidget的keyReleaseEvent()键盘按下事件函数
- 然后通过ignore()处理QMyLineEdit的keyReleaseEvent()事件函数
- 判断是否会继续执行QMyWidget父组件的keyReleaseEvent()事件函数
QLineEdit.h如下所示:
#ifndef QMYLINEEDIT_H
#define QMYLINEEDIT_H #include <QLineEdit>
#include <QtGui> class QMyLineEdit : public QLineEdit
{
Q_OBJECT public:
explicit QMyLineEdit(QWidget *parent = ); void keyReleaseEvent( QKeyEvent * event );
};
#endif // QMYLINEEDIT_H
QLineEdit.cpp如下所示:
#include "QMyLineEdit.h" QMyLineEdit::QMyLineEdit(QWidget *parent) :
QLineEdit(parent)
{
}
void QMyLineEdit::keyReleaseEvent( QKeyEvent * event )
{
qDebug()<<"QMyLineEdit::keyReleaseEvent";
qDebug()<<"key value:"<< event->key();
event->ignore(); //忽略当前事件
}
QMyWidget.h如下所示:
#ifndef QMYWIDGET_H
#define QMYWIDGET_H #include "QMyLineEdit.h"
#include <QWidget> class QMyWidget : public QWidget
{
Q_OBJECT
QMyLineEdit line; public:
explicit QMyWidget(QWidget *parent = );
void keyReleaseEvent( QKeyEvent * event ); }; #endif // QMYWIDGET_H
QMyWidget.cpp如下所示:
#include "QMyWidget.h" QMyWidget::QMyWidget(QWidget *parent) :
QWidget(parent),
line(this)
{
} void QMyWidget::keyReleaseEvent( QKeyEvent * event )
{
qDebug()<<"QMyWidget::keyReleaseEvent";
qDebug()<<"key value:"<< event->key(); QWidget::keyPressEvent(event);
}
main()函数如下所示:
int main(int argc, char *argv[])
{
QApplication a(argc, argv); QMyWidget w; w.show(); return a.exec();
}
效果如下:

可以看到成员调用了event->ignore()函数忽略事件后,同样也会继续进入QMyWidget类处理事件
Qt中的事件过滤器
- 事件过滤器可以对需要的组件接收到的事件进行过滤,以及监控
- 任意的QObject对象都可以作为事件过滤器使用
- 事件过滤器的实现,需要重写eventFilter()函数
- 组件要想被监控,则需要通过installEventFilter()安装事件过滤器
- 事件过滤器能够决定是否将事件转发给组件对象,如下图所示:

eventFilter函数体如下所示:
bool QObject::eventFilter ( QObject * watched, QEvent * event );
// watched:代表被监控的组件 event:代表要转发的事件
//返回true,表示该事件也被过滤掉(处理),无需再转发了
//返回false,则正常转发给watched
参考示例-实现文本框只允许输入数字:
class MainWindow : public QMainWindow
{
public:
MainWindow(); protected:
bool eventFilter(QObject *obj, QEvent *ev); private:
QTextEdit *textEdit;
};
MainWindow::MainWindow()
{
textEdit = new QTextEdit;
setCentralWidget(textEdit);
textEdit->setAttribute(Qt::WA_InputMethodEnabled, false); //禁止中文输入法
textEdit->installEventFilter(this);
} bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == textEdit)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
qDebug() << "Ate key press" << keyEvent->key();
switch(keyEvent->key()) //只接受0~9数字
{
case Qt::Key_0:
case Qt::Key_1:
case Qt::Key_2:
case Qt::Key_3:
case Qt::Key_4:
case Qt::Key_5:
case Qt::Key_6:
case Qt::Key_7:
case Qt::Key_8:
case Qt::Key_9:
return false;
default:
return true;
}
}
else
{
return false;
}
}
else
{
return QMainWindow::eventFilter(obj, event);
}
}
用户拖放事件
每个QWidget对象都能处理拖放事件
常用的拖放事件相关函数有:
void dragEnterEvent ( QDragEnterEvent * event ); //拖事件处理函数
void dropEvent ( QDropEvent * event ) ; //放事件处理函数
拖放事件所处理的数据是QMimeData类
- QMimeData类可以通过QDragEnterEvent 或者 QDropEvent 的成员函数QDropEvent()获取
- QMimeData支持多种不同类型的文件数据
MIME类型常用处理函数如下所示:

拖放事件的步骤如下:
1.在构造函数里通过setAcceptDrops(true)函数,让该组件能接受拖放事件
2.重写dragEnterEvent(QDragEnterEvent* event)函数并判断MIME类型
如果是期待的类型,则调用event ->acceptProposedAction();
否则调用 : event ->ignore();
3.重写dropEvent()函数并判断MIME类型
如果是期待的类型,则获取MIME数据并处理.
否则调用 : event ->ignore();
示例:
class MainWindow : public QMainWindow
{
private:
QTextEdit *textEdit;
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event); public:
MainWindow();
}; MainWindow::MainWindow()
{
textEdit = new QTextEdit;
setCentralWidget(textEdit);
textEdit->setAttribute(Qt::WA_InputMethodEnabled, false) ;
textEdit->installEventFilter(this);
this->setAcceptDrops(true);
} void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
if(event->mimeData()->hasUrls()) //判断拖的类型
{
event->acceptProposedAction();
}
else
{
event->ignore();
}
} void MainWindow::dropEvent(QDropEvent *event)
{
if(event->mimeData()->hasUrls()) //判断放的类型
{
textEdit->clear();
QList<QUrl> List = event->mimeData()->urls(); for(int i=;i<List.length();i++)
{
textEdit->insertPlainText(List[i].toLocalFile()+"\n");
}
}
else
{
event->ignore();
}
}
效果:

17.QT-事件处理分析、事件过滤器、拖放事件的更多相关文章
- QT事件过滤器(QT事件处理的5个层次:自己覆盖或过滤,父窗口过滤,Application过滤与通知)
Qt事件模型一个真正强大的特色是一个QObject 的实例能够管理另一个QObject 实例的事件. 让我们试着设想已经有了一个CustomerInfoDialog的小部件.CustomerInfoD ...
- Qt事件系统之五:事件过滤器和事件的发送
Qt提供了事件过滤器来实现在一个部件中监控其他多个部件的事件.事件过滤器与其他部件不同,它不是一个类,只是由两个函数组成的一种操作,用来完成一个部件对其他部件的事件的监视.这两个函数分别是 insta ...
- PyQt(Python+Qt)学习随笔:Qt Designer中部件的是否接受鼠标拖放事件的acceptDrops属性及含义
acceptDrops属性表示当前部件是否接受鼠标拖放事件,鼠标拖放应该是与鼠标拖拽结合在一起的,在Qt Designer中可以通过属性acceptDrops设置部件是否接受鼠标拖放事件.如果部件接受 ...
- 9、Qt 事件处理机制
原文地址:http://mobile.51cto.com/symbian-272812.htm 在Qt中,事件被封装成一个个对象,所有的事件均继承自抽象类QEvent. 接下来依次谈谈Qt中有谁来产生 ...
- QT开发(十二)——QT事件处理机制
一.QT事件简介 QT程序是事件驱动的, 程序的每个动作都是由内部某个事件所触发.QT事件的发生和处理成为程序运行的主线,存在于程序整个生命周期. 常见的QT事件类型如下: 键盘事件: 按键按下和松开 ...
- Qt事件处理机制
研一的时候开始使用Qt,感觉用Qt开发图形界面比MFC的一套框架来方便的多.后来由于项目的需要,也没有再接触Qt了.现在要重新拾起来,于是要从基础学起. Now,开始学习Qt事件处理机制. 先给出原文 ...
- 【转】Qt 事件处理机制 (下篇)
转自:http://mobile.51cto.com/symbian-272816.htm 在Qt中,事件被封装成一个个对象,所有的事件均继承自抽象类QEvent. 接下来依次谈谈Qt中有谁来产生.分 ...
- Qt 事件处理机制
Qt 事件处理机制 因为这篇文章写得特别好,将Qt的事件处理机制能够阐述的清晰有条理,并且便于学习.于是就装载过来了(本文做了排版,并删减了一些冗余的东西,希望原主勿怪),以供学习之用. 简介 在Qt ...
- Qt 事件处理机制 (下篇)
继续我们上一篇文章继续介绍,Qt 事件处理机制 (上篇) 介绍了Qt框架的事件处理机制:事件的产生.分发.接受和处理,并以视窗系统鼠标点击QWidget为例,对代码进行了剖析,向大家分析了Qt框架如何 ...
随机推荐
- 套接字输入缓冲装置——InternalInputBuffer
互联网的世界很复杂,信息从一端传向另一端过程也相当复杂,中间可能通过若干个硬件,为了提高发送和接收效率,在发送端及接收端都将引入缓冲区,所以两端的套接字都拥有各自的缓冲区,当然这种缓冲区的引入也带来了 ...
- 最简单的基于FFmpeg的内存读写的例子:内存转码器
===================================================== 最简单的基于FFmpeg的内存读写的例子系列文章列表: 最简单的基于FFmpeg的内存读写的 ...
- JUI/DWZ 分页 Servlet
分页介绍 参考:官方用户手册中的"分页组件" 分页思路服务器返回当前页的数据,总条数,再由js来生成分页标签.分页是配合服务器端来处理的, 不是存js做的分页. 因 ...
- hadoop队列管理(指定queue跑程序)
hadoop 升级到cdh5后,队列管理被取消,而是统一用资源池分配. hadoop2.0版本,Hadoop采用了平级队列组织方式,,管理员可将用户分到若干个扁平队列中,在每个队列中,可指定一个或几个 ...
- NDK工具开发Jni,Android studio jni开发
NDK工具开发JNI 对于JNI的作用,我这边就不详细说明了,百度google 有很多这样的介绍,这边着重详解AS使用NDK工具开发,调C的流程. 1,创建工程 2,创建native方法 //该类的路 ...
- JAVA之旅(十三)——线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this
JAVA之旅(十三)--线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this 我们继续上个篇幅接着讲线程的知识点 一.线程的安全性 当我们开启四个窗口(线程 ...
- Linux/Android多点触摸协议
链接点击打开链接 关于Linux多点触摸协议大家可以参考kernel中的文档:https://www.kernel.org/doc/Documentation/input/multi-touch-pr ...
- Python学习笔记 - dict和set
dict #!/usr/bin/env python3 # -*- coding: utf-8 -*- #dict >>> d = {'Michael': 95, 'Bob': 75 ...
- [Java]数组排序-选择排序 冒泡排序 插入排序
1 选择排序 原理:a 将数组中的每个元素,与第一个元素比较 如果这个元素小于第一个元素, 就将这个 两个元素交换. b 每轮使用a的规则, 可以选择出 ...
- Stochastic Gradient Descent 随机梯度下降法-R实现
随机梯度下降法 [转载时请注明来源]:http://www.cnblogs.com/runner-ljt/ Ljt 作为一个初学者,水平有限,欢迎交流指正. 批量梯度下降法在权值更新前对所有样本汇总 ...