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()函數獲取點擊了哪個按鈕