10_初探Qt中的消息处理

声明:此文章仅是本人在学习狄泰QT实验分析课程所做的笔记,文章中包含狄泰软件资料内容,一切版权归狄泰软件所有!
实验环境:ubuntu10 + Qt Creator2.4.1 + Qt SDK 4.7.4

1. Qt消息模型

Qt封装了具体操作系统的消息机制,Qt遵循经典的GUI消息驱动事件模型

问题:
1) Qt中如何表示用户消息
2) Qt中如何映射用户消息到消息处理函数
3) Qt中消息映射需要遵循什么规则

2. 信号(Signal)与槽(Slot)

(1) Qt中定义了与系统消息相关的概念:
信号(Signal):由操作系统产生的消息
槽(Slot):程序中的消息处理函数
连接(Connect):将系统消息绑定到消息处理函数

(2) Qt中消息处理机制

note: 信号到槽的连接必须发生在两个Qt类对象之间!!!

(3) Qt的核心QObject::connect函数

note:
1)在Qt中,消息用字符串进行描述
2)connect函数在消息名处理函数之间**建立映射

(4) Qt中的新关键字
SIGNAL:用于指定消息名
SLOT :用于指定消息处理函数名
Q_OBJECT:所有自定义槽的类必须在类声明的开始处加上Q_OBJECT
slots:用于在类中声明消息处理函数

编程说明:信号与槽的初探

#include 
#include 


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QPushButton b;

    b.setText("Click me to quit!");
    b.show();

    // connect函数
    QObject::connect(
                &b,
                SIGNAL(clicked()),
                &a,
                SLOT(quit()),
                Qt::AutoConnection);
    
    return a.exec();
}

输出结果:


点击后退出

3. 自定义槽

  • 只有QObject的子类才能自定义槽
  • 定义槽的类必须在声明的最开始处使用Q_OBJECT
  • 类中声明槽时需要使用slots关键字
  • 槽与所处理的信号在函数签名上必须一致
  • SIGNALSLOT所指定的名称中:可以包含参数类型, 不能包含具体的函数名

编程说明:为计算器实例添加消息处理函数
QCalcutorUI.h

#ifndef _QCALCULATORUI_H_
#define _QCALCULATORUI_H_

#include 
#include 
#include 

class QCalculatorUI : public QWidget
{
    Q_OBJECT
private:
    QLineEdit* m_edit;
    QPushButton* m_button[20];
    QCalculatorUI();
    bool construct();
private slots:              // 添加消息处理函数
    void onButtonClicked();
public:
    static QCalculatorUI* NewInstance();
    void show();
    ~QCalculatorUI();
    
};

#endif

QCalcutorUI.cpp

#include "QCalculatorUI.h"
#include 

QCalculatorUI::QCalculatorUI() : QWidget(NULL, Qt::WindowCloseButtonHint)
{

}

bool QCalculatorUI::construct()
{
    bool ret = true;
    const char* butText[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) && ret; ++i)
    {
        for(int j=0; (j<5) && ret; ++j)
        {
            m_button[i*5+j] = new QPushButton(this);
            if(m_button[i*5+j] != NULL)
            {
                m_button[i*5+j]->move(10+50*j, 50+50*i);
                m_button[i*5+j]->resize(40, 40);
                m_button[i*5+j]->setText(butText[i*5+j]);

                // 连接消息与消息处理函数
                connect(m_button[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::show()
{
    QWidget::show();
    setFixedSize(width(), height());
}

void QCalculatorUI::onButtonClicked()       // 实现消息处理函数
{
    QPushButton* btn = (QPushButton*)sender();  // 获取发送方对象的指针

    qDebug() << "onButtonClicked";
    qDebug() << btn->text();    // 获取发送方字符串
}

QCalculatorUI::~QCalculatorUI()
{
}

main.cpp

#include 
#include 
#include "QCalculatorUI.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QCalculatorUI* cal= QCalculatorUI::NewInstance();

    int ret = -1;

    if(cal != NULL)
    {
        cal->show();
        ret = a.exec();

        delete cal;
    }
    else
    {
        qDebug() << " Instance failure";
    }

    return ret;
}

4. 小贴士

  • 解决经典问题:Object::connect:NO such slot...
  1. 检查类是否继承于QObject
  2. 检查类声明的开始处是否添加Q_OBJECT
  3. 检查是否使用slots关键字进行槽声明
  4. 检查槽名称是否拼写错误
  5. 重新执行qmake

5. 小结

  • 信号与槽是Qt中的核心机制
  • 不同的Qt对象可以通过信号和槽进行通信
  • 只有QObject的子类才能自定义信号和槽
  • 使用信号和槽的类必须在声明的最开始处使用Q_OBJECT
  • 信号与处理函数在函数签名上必须一致

你可能感兴趣的:(10_初探Qt中的消息处理)