zoukankan      html  css  js  c++  java
  • 010_初探 Qt 中的消息处理

    在现代的 GUI 应用程序开发当中,主要分为两步:1.编写用户界面;2.处理用户操作后而产生的消息(编写消息处理函数来处理用户事件而产生的系统消息)

    一、 Qt 消息模型

    1. Qt 封装了具体操作系统的消息机制(Qt是现代的应用程序跨平台的开发框架)
    2. Qt 遵循经典的 GUI 消息驱动事件模型


    GUI应用程序是针对我们用户的,用户就会对GUI程序中的一些组件,比如:按钮,对话框等等做一些操作,当用户做了这些操作之后,首先知道这个用户事件的是操作系统,操作系统就会将用户的操作的翻译成应用程序消息,并且把这个消息发送给对应的应用程序。应用程序收到这个消息之后就会调用事先编写好的消息处理函数
    如果我们不关心中间的细节,简单的看开始和结束,就是用户做了一个操作,我们应用程序的某个函数就会被调用。

    二、 思考

    1. Qt 中如何表示用户消息?

    答:用字符串来描述消息

    2. Qt 中如何映射用户消息到消息处理函数?

    答:使用connet函数

    三、 信号与槽

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

    ---信号(Signal)
    • 由操作系统产生的消息
    ---槽(Slot)
    • 程序中的消息处理函数
    ---连接(Connect)
    • 将系统消息绑定到消息处理函数

    2、 Qt 中的消息处理机制


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

    3、 Qt 的核心-QObject::connet函数

    4、 Qt中的"新"关键字

    Qt 是基于C++的,Qt 又扩展了C++,在Qt里面引进了几个核心的关键字

    - SIGNAL
    • 用于指定消息名
    - SLOT
    • 用于指定消息处理函数名
    - Q_OBJECT
    • 所有自定义槽的类必须在类声明的开始处加上 Q_OBJECT
    - slots
    • 用于在类中声明消息处理函数

    四、 编程实验(初探信号与槽)---工程名:10-1.pro


    分析connet函数:连接信号与槽,将b这个按钮对象的click消息,这个click消息时一个预定义的消息,在Qt内库里面就已经定义好了,当按钮对象被点击了之后就会发送这个消息,现在我们通过connet函数将这个消息映射到a这个对象的quit成员函数上。那么映射之后click消息发生的时候quit函数就会被调用。

    五、 自定义槽

    • 只有 QObject的子类才能自定义槽
    • 定义槽的类必须在声明的最开始处使用 Q_OBJECT
    • 类中声明槽时需要使用 slots 关键字
    • 槽与所处理的信号在函数签名上必须一致。函数签名就是把函数名字去掉以后剩下的东西(参数、调用方式等)
    • SIGNAL 和 SLOT本质上就是用来指定消息的名字和消息处理函数的名字。那么在指定的名字当中,只能包含参数类型,不能包含具体的参数名

    六、 编程实验(为计算器实例添加消息处理函数)

    第一步:我们自己实现的Refactoring这个间接继承自QObject
    第二步:在类的声明最开始处使用Q_OBJECT
    第三步:声明槽(消息处理函数)时使用slots关键字,且槽与信号在函数签名上必须一致


    第四步:connet连接,将二十个按钮连接到同一个消息处理函数

    测试输出

    问:我们将二十个按钮映射到了同一个消息处理函数上,那应当如何区分是哪一个按钮被点击了呢?

    答:之所以我们消息处理函数有那么一丁点的特别,特别之处在于我们可以在消息处理函数内部调用sender这样的函数

    程序源码

    Refactoring_Calculator.h文件

    #ifndef REFACTORING_CALCULATOR_H
    #define REFACTORING_CALCULATOR_H
    
    #include <QWidget>
    #include <QLineEdit>
    #include <QPushButton>
    
    
    class Refactoring_Calculator : public QWidget
    {
        Q_OBJECT
    private:
        QLineEdit* m_edit;
        QPushButton* button_array[20];
        Refactoring_Calculator();
        bool construct();
    private slots:
        void OnButtonClicked();
    
    public:
        static Refactoring_Calculator* NewInstance();
        void show();
        ~Refactoring_Calculator();
    };
    
    #endif // REFACTORING_CALCULATOR_H
    

    Refactoring_Calculator.cpp文件

    #include "Refactoring_Calculator.h"
    #include <QDebug>
    
    Refactoring_Calculator::Refactoring_Calculator() : QWidget(NULL, Qt::WindowCloseButtonHint)
    {
    }
    
     bool Refactoring_Calculator::construct()
    {
         bool ret = true;
         const char* button_name[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; i++)
         {
             for(int j=0; j<5; j++)
             {
                 button_array[j + 5*i] = new QPushButton(this);
                 if( button_array[j + 5*i] != NULL )
                 {
                     button_array[j + 5*i]->resize(40, 40);
                     button_array[j + 5*i]->move(10 + 50*j, 50 + 50*i);
                     button_array[j + 5*i]->setText(button_name[j + 5*i]);
    
                     connect(button_array[j + 5*i], SIGNAL(clicked()), this, SLOT(OnButtonClicked()));
                 }
                 else
                 {
                     ret = false;
                 }
             }
         }
         return ret;
    }
    
     Refactoring_Calculator* Refactoring_Calculator::NewInstance()
    {
         Refactoring_Calculator* ret = new Refactoring_Calculator();
         if( !(ret && ret->construct()) )
         {
             delete ret;
             ret = NULL;
         }
         return ret;
    }
    
     void Refactoring_Calculator::show()
    {
         QWidget::show();
         setFixedSize(width(), height());
    }
    
    void Refactoring_Calculator::OnButtonClicked()
    {
        QPushButton* btn = (QPushButton*)sender();
        qDebug() << "OnButtonClicked()";
        qDebug() << btn->text();
    }
    
    Refactoring_Calculator::~Refactoring_Calculator()
    {
        if( m_edit != NULL )
        {
            delete m_edit;
        }
        for(int i=0; i<4; i++)
        {
            for(int j=0; j<5; j++)
            {
                if( button_array[j + i*5] != NULL )
                {
                    delete button_array[j + 5*i];
                }
            }
        }
    }
    

    main.cpp文件

    #include <QtGui/QApplication>
    #include <QWidget>
    #include <QLineEdit>
    #include <QPushButton>
    #include "Refactoring_Calculator.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Refactoring_Calculator* cal = Refactoring_Calculator::NewInstance();
        int ret = -1;
        if( cal != NULL )
        {
            cal->show();
            ret = a.exec();
            delete cal;
        }
    
        return ret;
    }
    

    七、 小贴士

    八、 小结

    • 信号与槽是 Qt 中的核心机制,不同的 Qt 对象可以通过信号和槽进行通信
    • 只有 QObject 的子类才能自定义信号和槽,并且使用信号和槽的类必须在声明的最开始处使用 Q_OBJECT
    • 信号与消息处理函数在函数签名上必须一致
  • 相关阅读:
    压缩和还原压缩的JS代码
    1.3(Spring学习笔记)Spring-AOP
    软件配置篇-MySQL下载及安装
    软件配置篇-java下载及安装
    1.2(Spring学习笔记)Spring中的Bean
    1.1(Spring学习笔记)Spring基础(BeanFactory、ApplicationContext 、依赖注入)
    1.6(学习笔记)EL表达式
    1.5 JSP标准标签库(JSTL)(核心标签 out、set、remove、if、choose、forEach、forTokens、redirect)
    1.4(学习笔记)JSP自定义标签
    随机算式
  • 原文地址:https://www.cnblogs.com/luosir520/p/12772134.html
Copyright © 2011-2022 走看看