zoukankan      html  css  js  c++  java
  • 第10课 初探 Qt 中的消息处理

    1. Qt消息模型

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

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

     

    2. 信号与槽

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

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

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

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

    (2)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)信号与处理函数在函数签名上必须一致。

  • 相关阅读:
    XMPP资源绑定(Resource Binding)与单台设备登录控制
    解决Eclipse建立Maven项目后无src/main/java资源文件夹的办法
    quartz做集群配置较短的时间间隔会重复执行任务的问题
    同一服务器部署多个tomcat时的端口号修改详情
    Java RSA加密算法生成公钥和私钥
    CSS3动画(重要)
    CSS3 过渡
    CSS3 3D 转换
    CSS3 2D 转换
    CSS3 文本效果(阴影)
  • 原文地址:https://www.cnblogs.com/5iedu/p/5433325.html
Copyright © 2011-2022 走看看