010_初探 Qt 中的消息处理
Posted luosir520
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了010_初探 Qt 中的消息处理相关的知识,希望对你有一定的参考价值。
在现代的 GUI 应用程序开发当中,主要分为两步:1.编写用户界面;2.处理用户操作后而产生的消息(编写消息处理函数来处理用户事件而产生的系统消息)
一、 Qt 消息模型
1. Qt 封装了具体操作系统的消息机制(Qt是现代的应用程序跨平台的开发框架)
2. Qt 遵循经典的 GUI 消息驱动事件模型
GUI应用程序是针对我们用户的,用户就会对GUI程序中的一些组件,比如:按钮,对话框等等做一些操作,当用户做了这些操作之后,首先知道这个用户事件的是操作系统
,操作系统就会将用户的操作的翻译成应用程序消息,并且把这个消息发送给对应的应用程序。应用程序收到这个消息之后就会调用事先编写好的消息处理函数
如果我们不关心中间的细节,简单的看开始和结束,就是用户做了一个操作,我们应用程序的某个函数就会被调用。
二、 思考
1. Qt 中如何表示用户消息?
答:用字符串来描述消息
2. Qt 中如何映射用户消息到消息处理函数?
答:使用connet函数
三、 信号与槽
1、 Qt 中定义了与系统消息相关的概念
---信号(Signal)
- 由操作系统产生的消息
---槽(Slot)
- 程序中的消息处理函数
---连接(Connect)
- 将系统消息绑定到消息处理函数
2、 Qt 中的消息处理机制
信号到槽的连接必须放生在两个 Qt 类对象之间!
3、 Qt 的核心-QObject::connet函数
4、 Qt中的"新"关键字
Qt 是基于C++的,Qt 又扩展了C++,在Qt里面引进了几个核心的关键字
- SIGNAL
- 用于指定消息名
- SLOT
- 用于指定消息处理函数名
- Q_OBJECT
- 所有自定义槽的类
必须在类声明的开始处加上 Q_OBJECT
- slots
- 用于在类中声明消息处理函数
四、 编程实验(初探信号与槽)---工程名:10-1.pro
分析connet函数:连接信号与槽,将b这个按钮对象的click消息,这个click消息时一个预定义的消息,在Qt内库里面就已经定义好了,当按钮对象被点击了之后就会发送这个消息,现在我们通过connet函数将这个消息映射到a这个对象的quit成员函数上。那么映射之后click消息发生的时候quit函数就会被调用。
五、 自定义槽
- 只有 QObject的子类才能自定义槽
- 定义槽的类必须在声明的最开始处使用 Q_OBJECT
- 类中声明槽时需要使用 slots 关键字
- 槽与所处理的信号在函数签名上必须一致。函数签名就是把函数名字去掉以后剩下的东西(参数、调用方式等)
- SIGNAL 和 SLOT本质上就是用来指定消息的名字和消息处理函数的名字。那么在指定的名字当中,只能包含参数类型,不能包含具体的参数名
六、 编程实验(为计算器实例添加消息处理函数)
第一步:我们自己实现的Refactoring这个间接继承自QObject
第二步:在类的声明最开始处使用Q_OBJECT
第三步:声明槽(消息处理函数)时使用slots关键字,且槽与信号在函数签名上必须一致
第四步:connet连接,将二十个按钮连接到同一个消息处理函数
测试输出
问:我们将二十个按钮映射到了同一个消息处理函数上,那应当如何区分是哪一个按钮被点击了呢?
答:之所以我们消息处理函数有那么一丁点的特别,特别之处在于我们可以在消息处理函数内部调用sender这样的函数
程序源码
Refactoring_Calculator.h文件
#ifndef REFACTORING_CALCULATOR_H
#define REFACTORING_CALCULATOR_H
#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
class Refactoring_Calculator : public QWidget
{
Q_OBJECT
private:
QLineEdit* m_edit;
QPushButton* button_array[20];
Refactoring_Calculator();
bool construct();
private slots:
void OnButtonClicked();
public:
static Refactoring_Calculator* NewInstance();
void show();
~Refactoring_Calculator();
};
#endif // REFACTORING_CALCULATOR_H
Refactoring_Calculator.cpp文件
#include "Refactoring_Calculator.h"
#include <QDebug>
Refactoring_Calculator::Refactoring_Calculator() : QWidget(NULL, Qt::WindowCloseButtonHint)
{
}
bool Refactoring_Calculator::construct()
{
bool ret = true;
const char* button_name[20] =
{
"7", "8", "9", "+", "(",
"4", "5", "6", "-", ")",
"1", "2", "3", "*", "<-",
"0", ".", "=", "/", "C",
};
m_edit = new QLineEdit(this);
if( m_edit != NULL )
{
m_edit->move(10, 10);
m_edit->resize(240, 30);
m_edit->setReadOnly(true);
}
else
{
ret = false;
}
for(int i=0; i<4; i++)
{
for(int j=0; j<5; j++)
{
button_array[j + 5*i] = new QPushButton(this);
if( button_array[j + 5*i] != NULL )
{
button_array[j + 5*i]->resize(40, 40);
button_array[j + 5*i]->move(10 + 50*j, 50 + 50*i);
button_array[j + 5*i]->setText(button_name[j + 5*i]);
connect(button_array[j + 5*i], SIGNAL(clicked()), this, SLOT(OnButtonClicked()));
}
else
{
ret = false;
}
}
}
return ret;
}
Refactoring_Calculator* Refactoring_Calculator::NewInstance()
{
Refactoring_Calculator* ret = new Refactoring_Calculator();
if( !(ret && ret->construct()) )
{
delete ret;
ret = NULL;
}
return ret;
}
void Refactoring_Calculator::show()
{
QWidget::show();
setFixedSize(width(), height());
}
void Refactoring_Calculator::OnButtonClicked()
{
QPushButton* btn = (QPushButton*)sender();
qDebug() << "OnButtonClicked()";
qDebug() << btn->text();
}
Refactoring_Calculator::~Refactoring_Calculator()
{
if( m_edit != NULL )
{
delete m_edit;
}
for(int i=0; i<4; i++)
{
for(int j=0; j<5; j++)
{
if( button_array[j + i*5] != NULL )
{
delete button_array[j + 5*i];
}
}
}
}
main.cpp文件
#include <QtGui/QApplication>
#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
#include "Refactoring_Calculator.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Refactoring_Calculator* cal = Refactoring_Calculator::NewInstance();
int ret = -1;
if( cal != NULL )
{
cal->show();
ret = a.exec();
delete cal;
}
return ret;
}
七、 小贴士
八、 小结
- 信号与槽是 Qt 中的核心机制,不同的 Qt 对象可以通过信号和槽进行通信
- 只有 QObject 的子类才能自定义信号和槽,并且使用信号和槽的类必须在声明的最开始处使用 Q_OBJECT
- 信号与消息处理函数在函数签名上必须一致
以上是关于010_初探 Qt 中的消息处理的主要内容,如果未能解决你的问题,请参考以下文章
2.QT-窗口组件(QWidget),QT坐标系统,初探消息处理(信号与槽)