- 基于操作系统才能运行
- GUI应用程序提供的功能必须由用户触发
- 用户操作界面时操作系统是第一个感知的
- 系统内核的消息通过事件处理转变成QT的信号
谁来产生事件? 最容易想到的是我们的输入设备,比如键盘、鼠标产生的keyPressEvent,keyReleaseEvent,mousePressEvent,mouseReleaseEvent事件(他们被封装成QMouseEvent和QKeyEvent)。
②Qt中事件的分发
对于Qt GUI程序,由QApplication来负责
类是整个Qt对象模型的心脏,事件处理机制是QObject三大职责(内存管理、内省(intropection)与事件处理制)之一。任何一个想要接受并处理事件的对象均须继承自QObject,可以选择重载QObject::event()函数或事件的处理权转给父类。
- Qt事件是一个QEvent(或子类)的对象
- 有时一个事件包含多个事件类型,比如鼠标事件又可以分为鼠标按下、双击、和移动多种操作
- 事件类型由QEvent类的枚举型QEvent::Type来表示,可由帮助文档进行查询
- Qt事件用于描述程序内部或外部发生的对应动作(描述的是操作系统发生来的消息,一个系统消息对应着一个消息事件)
- 任意QObject对象都具备时间处理的能力
QEvent及其子类对象
note:QEvent子类可以表示一个事件,但并不能处理这个事件
Qt 程序需要在main()函数创建一个QApplication对象,然后调用它的exec()函数。这个函数就是开始 Qt 的事件循环。在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件。当事件发生时,Qt 将创建一个事件对象。Qt 中所有事件类都继承于QEvent。在事件对象创建完毕后,Qt 将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是将这些事件对象按照它们不同的类型,分发给不同的事件处理器(event handler)。如上所述,event()函数主要用于事件的分发。
- Qt事件产生后会立即被分发到QWidget对象(QObject的子类,如按键QPushButton对象等)
- QWidget对象其内部会有一个event(QEVent*)函数被调用,进行事件处理
- event()根据事件类型调用不同的事件处理函数(默认的子函数)
- 在事件处理函数中发送Qt中预定义的信号
- 调用信号关联的槽函数
(4) QPushButton事件处理分析
①接收到鼠标事件
②QApplication调用QObject::event(QEvent*)成员函数来处理,进行事件的分派。
③调用QPushButton的mouseReleaseEvent(QMouseEvent*)成员函数
④QPushButton调用click()成员函数
⑤触发信号SIGNAL(clicked())
(5)实例
实例一:自定义事件处理函数
鼠标左键右键
wigth.h
1 #ifndef WIDGET_H
2 #define WIDGET_H
3
4 #include <QWidget>
5
6 class Widget : public QWidget
7 {
8 Q_OBJECT
9 protected:
10 void mousePressEvent(QMouseEvent *event);
11 public:
12 Widget(QWidget *parent = 0);
13
14 ~Widget();
15 };
16
17 #endif // WIDGET_H
18
19
20
widgth.cpp
1 #include "widget.h"
2 #include <QMouseEvent>
3 #include <QDebug>
4 #include <QMenu>
5 Widget::Widget(QWidget *parent)
6 : QWidget(parent)
7 {
8 }
9
10 void Widget::mousePressEvent(QMouseEvent *event)
11 {
12 if(event->button()==Qt::LeftButton)
13 {
14 qDebug()<<"LeftButton clicked!";
15 }
16 else if(event->button()==Qt::RightButton)
17 {
18 qDebug()<<"RightButton clicked!";
19
20 }
21
22 }
23
24 Widget::~Widget()
25 {
26
27 }
28
main.cpp
1 #include <QApplication>
2 #include "widget.h"
3
4 int main(int argc, char *argv[])
5 {
6 QApplication a(argc, argv);
7 Widget w;
8 w.show();
9
10 return a.exec();
11 }
12
1 #ifndef _QMYPUSHBUTTON_H_
2 #define _QMYPUSHBUTTON_H_
3
4 #include <QPushButton>
5
6 typedef void (QButtonListener)(QObject*,QMouseEvent*);
7
8 class QMyPushButton : public QPushButton
9 {
10 Q_OBJECT
11
12 protected:
13 QButtonListener* m_listener;
14
15 //重写QPushButton的事件处理函数 就有可能不会产生clicked信号
16 void mouseReleaseEvent(QMouseEvent *e);
17 public:
18 explicit QMyPushButton(QWidget* parent = 0, QButtonListener* listener = 0);
19 };
20
21 #endif // _QMYPUSHBUTTON_H_
//QMyPushButton.cpp
1 #include "QMyPushButton.h"
2 #include <QMouseEvent>
3
4 QMyPushButton::QMyPushButton(QWidget* parent, QButtonListener* listener):QPushButton(parent)
5 {
6 m_listener = listener;
7 }
8
9 //重写改写事件处理函数,会改变程序的行为。
10 void QMyPushButton::mouseReleaseEvent(QMouseEvent *e)
11 {
12 if(m_listener != NULL)
13 {
14 //调用自定义的事件处理函数,尽管按钮的clicked信号被连接到onMyButtonClicked槽函数,
15 //但因自定义的m_listener函数里并不触发clicked信号,从而槽函数不会被调用。
16 m_listener(this, e);
17 e->accept();//事件被接收,就不再传递到父QWidget
18
19 setDown(false); //按钮设置为“弹起”状态
20 }
21 else
22 {
23 //父类的mouseReleaseEvent会去调用clicked(),并触发SIGNAL(clicked())
24 //从而调用到连接到该信号的槽函数(本例为onMyButtonClicked())
25 QPushButton::mouseReleaseEvent(e); //调用父类
26 }
27 }
Widget.h
1 #ifndef _WIDGET_H_
2 #define _WIDGET_H_
3
4 #include <QWidget>
5 #include "QMyPushButton.h"
6
7 class Widget : public QWidget
8 {
9 Q_OBJECT
10 QMyPushButton myButton;
11
12 protected slots:
13 void onMyButtonClicked();
14
15 public:
16 Widget(QWidget *parent = 0);
17 ~Widget();
18 };
19
20 #endif // _WIDGET_H_
Widget.cpp
1 #include "Widget.h"
2 #include <qDebug>
3
4 //自定义事件处理函数
5 void onMyButtonMouseRelease(QObject* sender, QMouseEvent* e)
6 {
7 qDebug() << "onMyButtonMouseRelease(QObject* sender, QMouseEvent* e)";
8 }
9
10 Widget::Widget(QWidget *parent)
11 : QWidget(parent),myButton(this, onMyButtonMouseRelease) //实验2:myButton(this, 0)
12 {
13 myButton.setText("QMyPushButton");
14
15 connect(&myButton, SIGNAL(clicked()), this, SLOT(onMyButtonClicked()));
16 }
17
18 //槽函数,用于接收按钮的clicked信号
19 void Widget::onMyButtonClicked()
20 {
21 qDebug() << "onMyButtonClicked()" ;
22 }
23
24 Widget::~Widget()
25 {
26 }
main.cpp
#include "Widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
(4)事件(QEvent)和信号(SIGNAL)的不同
|
事件(QEvent) |
信号(SIGNAL) |
与QObject的关系 |
由具体对象进行处理 |
由具体对象主动产生 |
对程序影响 |
改写事件处理函数可能导致程序行为发生改变 |
信号是否存在对应的槽函数不会改变程序行为 |
两者的联系 |
一般而言,信号在具体的事件处理函数中产生 |
例如:单击界面上的按钮,那么就会产生鼠标事件QMouseEvent(不是按钮产生的),由于按钮被按下了,所以他会发出一个单击信号clicked()信号(是按钮产生的),这里只考虑单击信号而不用考虑鼠标事件,但如果要设计一个按钮,或者当单击按钮时让它产生别的效果,此时就要考虑鼠标事件了,由此,信号和事件是两个不同层面的东西,发出者不同,作用不同。Qt中,所有的QObject的子类实例均可对事件接收和处理!
3. 小结
(1)Qt中的事件和信号不同
(2)事件由QObject对象进行处理
(3)信号由QObject对象触发
(4)重写事件处理函数可能改变程序行为
(5)信号的触发不会对程序行为造成影响
(6)事件处理是在实际工程开发中应用非常普遍的