第10课 初探 Qt 中的消息处理

1. Qt消息模型

(1)Qt封装了具体操作系统的消息机制

(2)Qt遵循经典的GUI消息驱动事件模型

第10课 初探 Qt 中的消息处理 

2. 信号与槽

(1)Qt中定义了与系统消息相关的概念

  ①信号(Signal):由操作系统产生的消息

  ②槽(Slot):程序中的消息处理函数

  ③连接(Connect):将系统消息绑定到消息处理函数(映射规则)

(2)Qt中的消息处理机制

第10课 初探 Qt 中的消息处理 

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

  ①函数原型

bool connect(const QObject* sender,     //发送对象
             const char* signal,        //消息名
             const QObject* receiver,   //接收对象
             const char* method,        //接收者成员函数(消息处理函数)
             Qt::ConnectionType type = Qt::AutoConnection);

  ②在Qt中,消息用字符串进行描述,method是成员函数的名字(也是字符串类型)

  ③connect函数在消息名和处理函数之间建立映射

(4)Qt中的“新”关键字

  ①SIGNAL:用于指定消息名

  ②SLOT:用于指定消息处理函数名

  ③Q_OBJECT:所有自定义槽的类必须在类声明的开始处加上Q_OBJECT

  ④slots:用于在类中声明消息处理函数

【编程实验】初探信号和槽

#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QPushButton b; //顶级组件
    
    b.setText("Click me to quit!");
    b.show();

    //将按钮b的clicked消息映射到a的quit函数
    QObject::connect(&b, SIGNAL(clicked()), &a, SLOT(quit()));

    return a.exec();
}

3. 自定义槽

(1)只有QObject的子类才能自定义槽

(2)定义槽的类必须在声明的最开始处使用Q_OBJECT

(3)类中声明槽时需要使用slots关键字

(4)与所处理的信号在函数签名上必须一致(函数签名,即相同参数及类型、返回值

(5)SIGNAL和SLOT所指定的名称中,可以包含参数类型,但不能包含具体的参数名

【编程实验】为计算器实例添加消息处理函数

//main.cpp

#include <QApplication>
#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;
    }

    return ret;
}

//QCalculatorUI.h

#ifndef _QCALCULATORUI_H_
#define _QCALCULATORUI_H_

#include <QWidget>
#include <QLineEdit>
#include <QPushButton>

class QCalculatorUI : public QWidget
{
    //要自定义信号和槽,必须在最开始的这里添加Q_OBJECT
    Q_OBJECT
private:
    QLineEdit* m_edit;
    QPushButton* m_buttons[20];

    //二阶构造法:当new一个QLineEdit和一些按钮时可能会失败,所以采用二阶构造
    QCalculatorUI(); //第1阶——先隐藏构造函数
    bool construct();//第2阶

private slots: //声明槽时得加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)
{

}

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);//le的生命期由父组件来管理
    if( m_edit != NULL)
    {
        m_edit->move(10, 10);
        m_edit->resize(240, 30);
        m_edit->setReadOnly(true); //设置编辑框的只读属性
    }
    else
    {
        ret = false;
        return ret;
    }

    for(int i = 0; (i < 4) && ret; i++)
    {
        for(int j = 0; (j< 5) && ret; j++)
        {

            m_buttons[i * 5 + j] = new QPushButton(this);//按钮的生命期由父组件来管理
            if (m_buttons[i * 5 + j] != NULL)
            {
                m_buttons[i * 5 + j]->resize(40, 40);
                m_buttons[i * 5 + j]->move(10 + j * 50, 50 + i * 50);
                m_buttons[i * 5 + j]->setText(btnText[i * 5 + j]);

                //消息映射
                //1.消息名(信号)要加SIGNAL关键字,消息处理函数(槽):用SLOT关键字
                //2.信号和槽的函数签名必须一致,即都是无参的函数,返回值void
                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::show()
{
    QWidget::show();
    setFixedSize(width(), height());
}

void QCalculatorUI::onButtonClicked()
{
    //sender是QObject类的,用于表示消息的发送者
    QPushButton* btn = (QPushButton*)sender();

    qDebug() << "onButtonClicked()";
    qDebug() << btn->text();

}

 QCalculatorUI::~QCalculatorUI()
 {

 }

(6)小贴士:解决经典问题——Object::connect:No such slot…

  ①检查类是否继承于QObject

  ②检查类声明的开始处是否添加Q_OBJECT

  ③检查是否使用slots关键字进行槽声明

  ④检查槽的名称是否拼写错误

  ⑤重新执行qmake

4. 小结

(1)信号与槽是Qt中的核心机制

(2)不同的Qt对象可以通过信号和槽进行通信

(3)只有QObject的子类才能自定义信号和槽

(4)使用信号和槽的类必须在声明的最开始处使用Q_OBJECT

(5)信号与处理函数在函数签名上必须一致。

原文链接: https://www.cnblogs.com/5iedu/p/5433325.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    第10课 初探 Qt 中的消息处理

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/394375

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月3日 下午3:44
下一篇 2023年4月3日 下午3:44

相关推荐