Qt 消息模型
Qt 封装了具体操作系统的消息机制
Qt 遵循经典的 GUI 消息驱动事件模型
如果你只关注两头, 即用户做某个操作, 那么应用程序中的消息处理函数将被调用.
Qt 中如何表示用户消息? 用字符串来描述消息
Qt 中如何映射用户消息到消息处理函数? connect
Qt 中消息映射需要遵循什么规则?
信号与槽
Qt 中定义了与系统消息相关的概念
-- 信号 (Signal)
由操作系统产生的消息
-- 槽 (Slot)
程序中的消息处理函数
-- 连接 (Connect)
将系统消息绑定到消息处理函数
Qt 中的消息处理机制
信号到槽的连接必须发生在两个 Qt 类对象之间
Qt 的核心 --QObject::connect 函数
- bool connect(const QObject* sender, // 发送对象
- const QObject* signal, // 消息名
- const QObject* receiver, // 接收对象
- const char* method, // 接受对象的成员函数
- Qt::connectionType type = Qt::AutoConnection);
注意:
在 Qt 中, 消息用字符串进行描述
connect 函数在消息名和处理函数之间建立映射
Qt 中的新关键字
--SIGNAL
用于指定消息名
--SLOT
用于指定消息处理函数名
--Q_OBJECT
所有自定义槽的类必须在类声明的开始处加上 Q_OBJECT
--slots
用于在类中声明消息处理函数
初探信号与槽
- #include <QApplication>
- #include <QPushButton>
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- QPushButton btn;
- btn.setText("click me to quit...");
- btn.show();
- QObject::connect(&btn, SIGNAL(clicked()),&a, SLOT(quit()) );
- return a.exec();
- }
点击按钮对象, 当前应用程序退出.
自定义槽
只有 QObject 的子类才能自定义槽
定义槽的类必须在声明的最开始处使用 Q_OBJECT
类中声明槽时需要使用 slots 关键字
槽与所处理的信号在函数签名上必须一致 // 就是指信号如果带有参数类型, 那么槽就得带有参数类型. 总之两者要保持一致.
SIGNAL 和 SLOT 所指定的名称中:
-- 可以包含参数类型
-- 不能包含具体的参数名
- QCalculatorUI.h
- #ifndef _QCALCULATORUI_H_
- #define _QCALCULATORUIH_
- #include <QWidget>
- #include <QPushButton>
- #include <QLineEdit>
- class QCalculatorUI : public QWidget
- {
- Q_OBJECT
- private:
- QLineEdit* m_edit;
- QPushButton* m_buttons[20];
- QCalculatorUI();
- bool construct();
- private slots:
- void onButtonClicked();
- public:
- static QCalculatorUI* NewInstance();
- void show();
- ~QCalculatorUI();
- };
- #endif // _QCALCULATORUI_H_
- QCalculatorUI.cpp
- #include "QCalculatorUI.h"
- #include <QDebug>
- QCalculatorUI::QCalculatorUI(): QWidget(NULL,Qt::WindowCloseButtonHint) // 此处 QCalculatorUI 就是作为顶层窗口存在的, 虽然这个地方继承自 QWidget, 但是赋值为 NULL, 相当于它是没有父类的 (但是实际上还是有的).
- // 将窗口中的最大化和最小化去掉
- {
- // 因为 QLineEdit 与 QCalculatorUI 以及 QPushButton 与 QCalculatorUI 是组合关系, 那么就应该同生死, 因此需要在构造函数对其定义. 因为此处涉及到在堆上申请内存空间, 因此需要
- // 使用二阶构造
- }
- bool QCalculatorUI::construct()
- {
- bool ret = true;
- const char* btnText[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); // 使 QLineEdit 只读
- }
- else
- {
- ret = false;
- }
- for(int i=0; (i<4) && ret; i++)
- {
- for(int j=0; (j<5) && ret; j++)
- {
- if(m_buttons[i*5 + j] != NULL)
- {
- m_buttons[i*5 + j] = new QPushButton(this);
- m_buttons[i*5 + j]->move(10 + (10 + 40)*j, 50 + (10 + 40)*i);
- m_buttons[i*5 + j]->resize(40,40);
- m_buttons[i*5 + j]->setText(btnText[i*5 + j]);
- connect(m_buttons[i*5 + j],SIGNAL(clicked()), this, SLOT(onButtonClicked()));
- }
- else
- {
- ret = false;
- }
- }
- }
- return ret;
- }
- QCalculatorUI* QCalculatorUI::NewInstance()
- {
- QCalculatorUI* ret = new QCalculatorUI();
- if((ret == NULL) || !(ret->construct()))
- {
- delete ret;
- ret = NULL;
- }
- return ret;
- }
- void QCalculatorUI::onButtonClicked()
- {
- QPushButton* btn = (QPushButton*)sender();
- qDebug()<<"onButtonClicked";
- qDebug() << btn->text();
- }
- void QCalculatorUI::show()
- {
- QWidget::show();
- this->setFixedSize(this->width(),this->height()); // 固定窗口的大小
- }
- QCalculatorUI::~QCalculatorUI()
- {
- }
- main.cpp
- #include <QApplication>
- #include "QCalculatorUI.h"
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- QCalculatorUI* cal = QCalculatorUI::NewInstance();
- int ret = 0;
- if(cal != NULL)
- {
- cal->show();
- ret = a.exec();
- delete cal; // 当程序运行到最后时, 将生成的 cal 对象释放掉.
- }
- return ret;
- }
将 20 个按钮映射到了同一个消息处理函数中, 如何辨别哪个按钮被点击了呢?
在消息处理函数中: QPushButton* btn = (QPushButton*)sender();, 通过 sender() 函数获取点击了哪个按钮
来源: http://www.bubuko.com/infodetail-3345345.html