1、GUI程序原理回顾
图形界面应用程序的消息处理模型
2、思考
操作系统发送的消息如何转变成Qt信号?
3、Qt中的事件处理
Qt平台将系统产生的消息转换为Qt事件
- Qt事件是一个QEvent的对象
- Qt事件用于描述程序内部或外部发生的动作
- 任意的QObject对象都具备事件处理的能力
GUI应用程序的事件处理方式
1. Qt事件产生后立即被分发到QWdget对象
2. QWidget中的event(QEvent*)进行事件处理
3. event()根据事件类型调用不同的事件处理函数
4. 在事件处理函数中发送Qt中预定义的信号
5. 调用信号关联的槽函数
场景分析:按钮点击
QPushButton事件处理分析
1、接收到鼠标事件
2、调用event(QEvent*)成员函数
3、调用mouseReleaseEvent(QMouseEvent*)成员函数
4、调用click()成员函数
5. 触发信号SIGNAL(clicked())
4、编程实验
自定义事件处理函数 38-1.pro
QMyPushButton.h
#ifndef _QMYPUSHBUTTON_H_
#define _QMYPUSHBUTTON_H_
#include <QPushButton>
typedef void (QButtonListener)(QObject*, QMouseEvent*);
class QMyPushButton : public QPushButton
{
Q_OBJECT
protected:
QButtonListener* m_listener;
void mouseReleaseEvent(QMouseEvent *e);
public:
explicit QMyPushButton(QWidget* parent = 0, QButtonListener* listener = 0);
signals:
public slots:
};
#endif // _QMYPUSHBUTTON_H_
QMyPushButton.cpp
#include "QMyPushButton.h"
#include <QMouseEvent>
QMyPushButton::QMyPushButton(QWidget* parent, QButtonListener* listener) : QPushButton(parent)
{
m_listener = listener;
}
void QMyPushButton::mouseReleaseEvent(QMouseEvent *e)//重写事件处理函数,事件分配后会被调用
{
if( m_listener != NULL )
{
m_listener(this, e);//调用成员指针所指向的函数onMyButtonMouseRelease,没有预定义的信号
e->accept();//标记当前事件已经被处理
setDown(false);//更新UI,按钮弹起
}
else
{
QPushButton::mouseReleaseEvent(e);
}
}
Widget.h
#ifndef _WIDGET_H_
#define _WIDGET_H_
#include <QtGui/QWidget>
#include "QMyPushButton.h"
class Widget : public QWidget
{
Q_OBJECT
QMyPushButton myButton;
protected slots:
void onMyButtonClicked();
public:
Widget(QWidget *parent = 0);
~Widget();
};
#endif // _WIDGET_H_
Widget.cpp
#include "Widget.h"
#include <QDebug>
void onMyButtonMouseRelease(QObject* sender, QMouseEvent* e)
{
qDebug() << "onMyButtonMouseRelease(QObject* sender, QMouseEvent* e)";
}
Widget::Widget(QWidget *parent) : QWidget(parent), myButton(this, onMyButtonMouseRelease)
{
myButton.setText("QMyPushButton");
connect(&myButton, SIGNAL(clicked()), this, SLOT(onMyButtonClicked()));
}
void Widget::onMyButtonClicked()
{
qDebug() << "onMyButtonClicked()";
}
Widget::~Widget()
{
}
main.cpp
#include <QtGui/QApplication>
#include "Widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
5、Qt中的事件处理
事件(QEvent)和信号(SIGNAL)不同
-事件由具体对象进行处理
-信号由具体对象主动产生
-改写事件处理函数可能导致程序行为发生改变
-信号是否存在对应的槽函数不会改变程序行为
-一般而言,信号在具体的事件处理函数中产生
6、文本编辑器中的关闭操作
7、编程实验
文本编辑器的关闭操作 NotePad.pro
发现QMainWindow和QWidget中没有信号可以解决当前问题
可以考虑重写事件处理函数
找到了void Widget::closeEvent(QcloseEvent* event)
MainWindow.h新增
protected:
void closeEvent(QCloseEvent* e);
MainWindowSlots.cpp新增
void MainWindow::closeEvent(QCloseEvent* e)
{
preEditorChange();//确认是否保存
if( !m_isTextChanged )
{
QMainWindow::closeEvent(e);
}
else
{
e->ignore();
}
}
8、小结
Qt中的事件(QEvent)和信号(SIGNAL)不同
事件由QObject的对象进行处理
信号由QObject对象触发
重写事件处理函数可能改变程序行为
信号的触发不会对程序行为造成影响
事件处理是在实际工程开发中的应用非常普遍