Qt_day3_信号槽

打印 上一主题 下一主题

主题 1645|帖子 1645|积分 4937

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目录
信号槽
1. 概念
2. 函数原型
3. 连接方式
3.1 自带信号 → 自带槽
3.2 自带信号 → 自定义槽
3.3 自定义信号
4. 信号槽传参
5. 对应关系
5.1 一对多
5.2 多对一


信号槽


      1. 概念

   
       之前的程序界面只能看,不能交互,信号槽可以让界面举行人机交互。
       信号槽是Qt在C++底子上新增的特性,类似于其他编程中的回调机制,其目的是实现对象之间的通信。
   使用信号槽必要具备两个先决条件:
   

  • 通信的对象必须继承自QObject
   QObject是Qt全部对象的基类,内部规定了Qt最底子的对象特性。
   

  • 类中要包含Q_OBJECT宏
   

   2. 函数原型

   
   信号槽的建立是通过connect函数实现的。
   
  1. // 信号槽连接函数
  2. // 参数1:发射者,因发起的对象n.
  3. // 参数2:信号函数,因的动作v.,需要使用SIGNAL()包裹函数名称
  4. // 参数3:接收者,果执行的对象n.
  5. // 参数4:槽函数,果的动作v.,需要使用SLOT()包裹函数名称
  6. QObject::​connect(const QObject * sender,
  7.                                     const char * signal,
  8.                                     const QObject * receiver,
  9.                                     const char * slot)                [static]
复制代码

           信号函数一定来自于发射者,槽函数一定来自于吸收者。信号槽的连接必须在发射者对象和吸收者对象创建完成后举行,如果成功连接后,发射者或吸收者对象销毁了,连接断开。
       信号槽的连接也可以程序员手动断开,只必要把connect函数改为disconnect即可,参数保持不变。
   
   3. 连接方式

   
   为了讲课,按照难易程度分为三种连接方式:
   

  • 自带信号 → 自带槽
  • 自带信号 → 自定义槽
  • 自定义信号 → 槽

   3.1 自带信号 → 自带槽

   
       这种连接方式是最简单的连接方式,因为信号函数和槽函数都是Qt内置的,程序员只必要找到连接的四个参数,直接连接即可。
   
   【例子】点击按钮,关闭窗口。
   分析:
   参数1:发射者——按钮对象
   参数2:信号函数——点击
  
  1. void QAbstractButton::​clicked()                    [signals]
复制代码
              参数3:吸收者——窗口对象
     参数4:槽函数——关闭
           
  1. bool QWidget::​close()                            [slot]
复制代码

       dialog.h
  
  1. #ifndef DIALOG_H
  2. #define DIALOG_H
  3. #include <QDialog>
  4. #include <QPushButton>
  5. class Dialog : public QDialog
  6. {
  7.     Q_OBJECT
  8. public:
  9.     Dialog(QWidget *parent = 0);
  10.     ~Dialog();
  11. private:
  12.     QPushButton *btn;
  13. };
  14. #endif // DIALOG_H
复制代码
  
            dialog.cpp
     
   
  1. #include "dialog.h"
  2. Dialog::Dialog(QWidget *parent)
  3.     : QDialog(parent)
  4. {
  5.     resize(400,400);
  6.     btn = new QPushButton("关闭",this);
  7.     btn->move(100,100);
  8.     //  参数1:发射者——按钮对象
  9.     //        参数2:信号函数——点击
  10.     //        参数3:接收者——窗口对象
  11.     //        参数4:槽函数——关闭
  12.     connect(btn,SIGNAL(clicked()),this,SLOT(close()));
  13. }
  14. Dialog::~Dialog()
  15. {
  16.     delete btn;
  17. }
复制代码
   
                       3.2 自带信号 → 自定义槽

      
           这种连接方式是使用的最多的一种连接方式,因为在实际开发中,Qt无法预设全部的槽函数环境,对于复杂的操纵执行逻辑,必要程序员手动编写槽函数。
       槽函数是一种特殊的成员函数。
      
       【例子】点击按钮,窗口向右下角移动10个像素,而且后台输出当前窗口的位置。
      
       dialog.h
               
  1. #ifndef DIALOG_H
  2. #define DIALOG_H
  3. #include <QDialog>
  4. #include <QPushButton>
  5. #include <QDebug>
  6. class Dialog : public QDialog
  7. {
  8.     Q_OBJECT
  9. public:
  10.     Dialog(QWidget *parent = 0);
  11.     ~Dialog();
  12. private:
  13.     QPushButton *btn;
  14.     // 槽函数的声明
  15. private slots: // 最小权限原则
  16.    void mySlot(); // 自定义槽函数
  17. };
  18. #endif // DIALOG_H
复制代码
   
                       dialog.cpp
                     
  1. #include "dialog.h"
  2. Dialog::Dialog(QWidget *parent)
  3.     : QDialog(parent)
  4. {
  5.     resize(400,400);
  6.     btn = new QPushButton("关闭",this);
  7.     btn->move(100,100);
  8.     // 连接信号槽
  9.     connect(btn,SIGNAL(clicked()),
  10.             this,SLOT(mySlot()));
  11. }
  12. void Dialog::mySlot()
  13. {
  14.     // 先获得当前坐标
  15.     int x = this->x();
  16.     int y = this->y();
  17.     // 移动
  18.     move(x+10,y+10);
  19.     // 输出当前窗口位置
  20.     qDebug() << this->x() << this->y();
  21. }
  22. Dialog::~Dialog()
  23. {
  24.     delete btn;
  25. }
复制代码

       3.3 自定义信号

   
       自定义信号通常用于办理一些对象之间“远距离”通信问题,本节属于强利用用,因此并不是问题最优解,只是为了展示自定义信号的使用方式。
   【例子】点击按钮,按钮上表现点击的次数。
   先忽略自定义信号,展示正常解法:
   


       dialog.h
  
  1. #ifndef DIALOG_H
  2. #define DIALOG_H
  3. #include <QDialog>
  4. #include <QPushButton>
  5. #include <QDebug>
  6. class Dialog : public QDialog
  7. {
  8.     Q_OBJECT
  9. public:
  10.     Dialog(QWidget *parent = 0);
  11.     ~Dialog();
  12. private:
  13.     QPushButton* btn;
  14.     int count;
  15. private slots:
  16.     void btnClickedSlot(); // 点击按钮的槽函数
  17. };
  18. #endif // DIALOG_H
复制代码
  
               dialog.cpp
   
  1. #include "dialog.h"
  2. Dialog::Dialog(QWidget *parent)
  3.     : QDialog(parent),count(0) // 构造初始化列表
  4. {
  5.     resize(400,400);
  6.     btn = new QPushButton("0",this);
  7.     btn->move(200,200);
  8.     connect(btn,SIGNAL(clicked()),
  9.             this,SLOT(btnClickedSlot()));
  10. }
  11. void Dialog::btnClickedSlot()
  12. {
  13.     count++;
  14.     // int → QString
  15.     QString text = QString::number(count);
  16.     // 设置到按钮上显示
  17.     btn->setText(text);
  18. }
  19. Dialog::~Dialog()
  20. {
  21.     delete btn;
  22. }
复制代码
   
                       基于上面的解法,强行增长自定义信号发射环节:
               
     

         
                    信号函数是一种特殊的函数,只有声明没有定义,声明后可以直接配合emit关键字发射。
     dialog.h
   
  1. #ifndef DIALOG_H
  2. #define DIALOG_H
  3. #include <QDialog>
  4. #include <QPushButton>
  5. #include <QDebug>
  6. class Dialog : public QDialog
  7. {
  8.     Q_OBJECT
  9. public:
  10.     Dialog(QWidget *parent = 0);
  11.     ~Dialog();
  12. private:
  13.     QPushButton* btn;
  14.     int count;
  15. signals:
  16.     void countSignal(); // 自定义信号
  17. private slots:
  18.     void btnClickedSlot(); // 点击按钮的槽函数
  19.     void countSlot(); // 与自定义信号连接的槽函数
  20. };
  21. #endif // DIALOG_H
复制代码
   
                       dialog.cpp
      
  1. #include "dialog.h"
  2. Dialog::Dialog(QWidget *parent)
  3.     : QDialog(parent),count(0) // 构造初始化列表
  4. {
  5.     resize(400,400);
  6.     btn = new QPushButton("0",this);
  7.     btn->move(200,200);
  8.     connect(btn,SIGNAL(clicked()),
  9.             this,SLOT(btnClickedSlot()));
  10.     connect(this,SIGNAL(countSignal()),
  11.             this,SLOT(countSlot()));
  12. }
  13. void Dialog::btnClickedSlot()
  14. {
  15.     count++;
  16.     // 发射自定义信号
  17.     emit countSignal();
  18. }
  19. /**
  20. * @brief Dialog::countSlot
  21. * 中转之后更新按钮显示的槽函数
  22. */
  23. void Dialog::countSlot()
  24. {
  25.     QString text = QString::number(count);
  26.     btn->setText(text);
  27. }
  28. Dialog::~Dialog()
  29. {
  30.     delete btn;
  31. }
复制代码
      
                               4. 信号槽传参

         
             信号槽可以举行参数传递,信号函数携带参数发射,槽函数可以收到此参数。
         
         dialog.h
        
  1. #ifndef DIALOG_H
  2. #define DIALOG_H
  3. #include <QDialog>
  4. #include <QPushButton>
  5. #include <QDebug>
  6. class Dialog : public QDialog
  7. {
  8.     Q_OBJECT
  9. public:
  10.     Dialog(QWidget *parent = 0);
  11.     ~Dialog();
  12. private:
  13.     QPushButton* btn;
  14.     int count;
  15. signals:
  16.     void countSignal(int); // 自定义信号
  17. private slots:
  18.     void btnClickedSlot(); // 点击按钮的槽函数
  19.     void countSlot(int); // 与自定义信号连接的槽函数
  20. };
  21. #endif // DIALOG_H
复制代码
        
                                       dialog.cpp
         
  1. #include "dialog.h"
  2. Dialog::Dialog(QWidget *parent)
  3.     : QDialog(parent),count(0) // 构造初始化列表
  4. {
  5.     resize(400,400);
  6.     btn = new QPushButton("0",this);
  7.     btn->move(200,200);
  8.     connect(btn,SIGNAL(clicked()),
  9.             this,SLOT(btnClickedSlot()));
  10.     connect(this,SIGNAL(countSignal(int)),
  11.             this,SLOT(countSlot(int)));
  12. }
  13. void Dialog::btnClickedSlot()
  14. {
  15.     count++;
  16.     // 发射自定义信号(携带参数)
  17.     emit countSignal(count);
  18. }
  19. /**
  20. * @brief Dialog::countSlot
  21. * count参数是信号函数发来的,不是成员变量
  22. * 中转之后更新按钮显示的槽函数
  23. */
  24. void Dialog::countSlot(int count)
  25. {
  26.     QString text = QString::number(count);
  27.     btn->setText(text);
  28. }
  29. Dialog::~Dialog()
  30. {
  31.     delete btn;
  32. }
复制代码
         
                                               必要留意的是:
            

  • 理论上可以传递任意多个参数
  • 信号函数的参数个数必须大于等于槽函数的参数个数
  • 参数类型必要匹配
                                 
                                               5. 对应关系

            
                 同一个信号可以连接到多个槽(一对多),多个信号也可以连接到同一个槽(多对一)。
            

             5.1 一对多

            
                 槽函数也是成员函数,因此在一对多的连接关系中,把连接的多个槽函数可以看做是普通的成员函数,归并为一个槽函数。
            
             dialog.h
                                                  
  1. #ifndef DIALOG_H
  2. #define DIALOG_H
  3. #include <QDialog>
  4. #include <QPushButton>
  5. #include <QDebug>
  6. class Dialog : public QDialog
  7. {
  8.     Q_OBJECT
  9. public:
  10.     Dialog(QWidget *parent = 0);
  11.     ~Dialog();
  12. private:
  13.     QPushButton* btn1;
  14.     QPushButton* btn2;
  15. private slots:
  16.     void btnClickedSlot1();
  17.     void btnClickedSlot2();
  18.     void btnClickedSlot3(); // 3 = 1 + 2
  19. };
  20. #endif // DIALOG_H
复制代码
        
                              dialog.cpp
                           
  1. #include "dialog.h"
  2. Dialog::Dialog(QWidget *parent)
  3.     : QDialog(parent)
  4. {
  5.     resize(400,400);
  6.     btn1 = new QPushButton("一对多", this);
  7.     btn1->move(200,100);
  8.     btn2 = new QPushButton("一对一", this);
  9.     btn2->move(100,200);
  10.     // 一对多
  11.     connect(btn1,SIGNAL(clicked()),
  12.             this,SLOT(btnClickedSlot1()));
  13.     connect(btn1,SIGNAL(clicked()),
  14.             this,SLOT(btnClickedSlot2()));
  15.     // 一对一
  16.     connect(btn2,SIGNAL(clicked()),
  17.             this,SLOT(btnClickedSlot3()));
  18. }
  19. void Dialog::btnClickedSlot1()
  20. {
  21.     qDebug() << "A";
  22. }
  23. void Dialog::btnClickedSlot2()
  24. {
  25.     qDebug() << "B";
  26. }
  27. void Dialog::btnClickedSlot3()
  28. {
  29.     // 直接把Slot1和Slot2两个函数当做普通的成员函数,
  30.     // 使用this指针调用
  31.     btnClickedSlot1();
  32.     btnClickedSlot2();
  33. }
  34. Dialog::~Dialog()
  35. {
  36.     delete btn1;
  37. }
复制代码
        
                                       5.2 多对一

           
               多对一的连接方式下,槽函数无法区分信号来源,可以在槽函数中调用sender函数获取发射者对象,从而判定信号来源。
           
         
  1. // 在槽函数中调用,返回发射者对象
  2. QObject * QObject::​sender() const
复制代码
         
                                    dialog.h
            
  1. #ifndef DIALOG_H
  2. #define DIALOG_H
  3. #include <QDialog>
  4. #include <QPushButton>
  5. #include <QDebug>
  6. class Dialog : public QDialog
  7. {
  8.     Q_OBJECT
  9. public:
  10.     Dialog(QWidget *parent = 0);
  11.     ~Dialog();
  12. private:
  13.     QPushButton* btn1;
  14.     QPushButton* btn2;
  15. private slots:
  16.     void btnsClickedSlot();
  17. };
  18. #endif // DIALOG_H
复制代码
            
                           dialog.cpp                                                                                         
  1. #include "dialog.h"
  2. Dialog::Dialog(QWidget *parent)
  3.     : QDialog(parent)
  4. {
  5.     resize(400,400);
  6.     btn1 = new QPushButton("A",this);
  7.     btn2 = new QPushButton("B",this);
  8.     btn1->move(150,100);
  9.     btn2->move(150,200);
  10.     // 多对一
  11.     connect(btn1,SIGNAL(clicked()),
  12.             this,SLOT(btnsClickedSlot()));
  13.     connect(btn2,SIGNAL(clicked()),
  14.             this,SLOT(btnsClickedSlot()));
  15. }
  16. void Dialog::btnsClickedSlot()
  17. {
  18.     if(btn1 == sender())
  19.     {
  20.         qDebug() << "点击了按钮1";
  21.     }else if(btn2 == sender())
  22.     {
  23.         qDebug() << "点击了按钮2";
  24.     }
  25.     qDebug() << "槽函数触发!";
  26. }
  27. Dialog::~Dialog()
  28. {
  29.     delete btn1;
  30.     delete btn2;
  31. }
复制代码
      

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用多少眼泪才能让你相信

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表