• QT当中的connect+eventFilter函数全解


    【1】 connect函数举例

    原型

    [static] QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)

    解释

    创建从发送方对象中的信号到接收方对象中的方法的给定类型的连接。
    返回以后可用于断开连接的连接的句柄。

    举例

    在指定信号和方法时,必须使用SIGNAL()和SLOT()宏
    例如:

     QLabel *label = new QLabel;//标签对象
      QScrollBar *scrollBar = new QScrollBar;//滚动条对象
    QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
                       label,  SLOT(setNum(int)));
    • 1
    • 2
    • 3

    1、参数说明:结合上面的函数声明用例来说一下,函数的各个参数

    1.1第一个参数 const QObject *sender 发送信号的对象 类型是QObject我们常用的QWidget,一些控件定时器等都继承自QObject,都可以作为信号发送者
    1.2第二个参数 const char *signal 为要发射的信号 信号实际上是一类函数,这类函数声明在Q_SIGNALS:后面。当对象改变其状态时,信号就由该对象发射 (emit) 出去,而且对象只负责发送信号,它不知道另一端是谁在接收这个信号。这样就做到了真正的信息封装,能确保对象被当作一个真正的软件组件来使用。上述例子中是SIGNAL(valueChanged(int))
    1.3第三个参数 const QObject *receiver 接收信号的对象 在上述例子中这个参数为label,表明是label部件接收,当这个参数是this时可以省略,因为connect函数的另外一个重载形式默认参数是this
    1.4第四个参数 const char *method 是要执行的槽函数 第四个参数是要执行的槽,在上述例子中是SLOT(setNum(int))。一般我们使用发送者触发信号,然后执行接收者的槽函数。这个参数要可以指定一个信号,实现信号与信号的关联。这个参数指定的槽在声明时必须使用slots关键字。
    1.5第五个参数 Qt::ConnectionType type连接类型,一般使用默认值

    此示例可确保标签始终显示当前的滚动条值。请注意,信号和插槽参数不能包含任何变量名,而只能包含变量类型。

    1connect(mcu_monitor,SIGNAL(Sig_SetValue(int, QString)),data_lib,SLOT(Set_Value(int, QString))); 
      `mcu_monitor`:监控对象指针 
      `Sig_SetValue(int, QString)`:监控类里面的自定义信号函数
      `data_lib`:数据整理类指针对象
      `Set_Value(int, QString)`:数据类里面的槽函数
      • 1
      • 2
      • 3

      错误示范:带变量名

      // WRONG
        QObject::connect(scrollBar, SIGNAL(valueChanged(int value)),
                         label, SLOT(setNum(int value)));
      • 1
      • 2

      一个信号也可以连接到另一个信号:
      举例如下:

        class MyWidget : public QWidget
        {
            Q_OBJECT
      
      
        public:
            MyWidget();//成员函数
      
      
        signals:
            void buttonClicked();//按钮信号
      
      
        private:
            QPushButton *myButton;//按对象指针
        };
      
      
        MyWidget::MyWidget()//无参构造函数
        {
            myButton = new QPushButton(this);//申请空间
            connect(myButton, SIGNAL(clicked()),this, SIGNAL(buttonClicked()));//单击按钮触发 SIGNAL(buttonClicked())信号
        }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22

      【2】Q_SLOTS

      当您希望使用第三方信号/插槽机制使用Qt信号和插槽时,请使用此宏来替换类声明中的插槽关键字。

      使用具有第三方信号和插槽的Qt

      可以使用第三方Qt槽/机制。您甚至可以在同一项目中使用这两种机制。只需将下面一行添加到您的qmake项目(.pro)文件中。
      该宏通常在.pro文件中使用配置变量指定no_keywords时使用,但即使没有指定no_keywords,也可以使用该宏。

      CONFIG += no_keywords

        在这里插入图片描述

        它告诉Qt不要定义moc keywords ,signals, slots,emit,和因为这些名称将被第三方库使用,例如Boost。然后,要继续使用带有no_keywords标志的Qt信号和插槽,只需将相应的`Qt宏Q_SIGNALS(或Q_SIGNAL)、Q_SLOTS(或Q_SLOT)和Q_EMIT。

        【3】Q_SLOT

        这是一个额外的宏,允许您将单个函数标记为插槽。它可能非常有用,特别是当您使用不理解插槽或Q_SLOTS组的第三方源代码解析器时。
        当您希望使用第三方信号/插槽机制使用Qt信号和插槽时,请使用此宏来替换类声明中的插槽关键字。
        该宏通常在.pro文件中使用配置变量指定no_keywords时使用,但即使没有指定no_keywords,也可以使用该宏。

        CONFIG += no_keywords

          【4】Q_SIGNALS

          当您想要使用第三方信号/插槽机制使用Qt信号和插槽时,可以使用此宏来替换类声明中的信号关键字。
          宏通常在.pro文件中使用配置变量指定no_keywords时使用,但即使没有指定no_keywords,也可以使用该宏。

          CONFIG += no_keywords

            【5】Q_SIGNAL

            这是一个额外的宏,它允许您将单个函数标记为信号。它可能非常有用,特别是当您使用一个不理解信号或Q_SIGNALS组的第三方源代码解析器时。
            当您希望使用第三方信号/插槽机制使用Qt信号和插槽时,请使用此宏来替换类声明中的信号关键字。
            该宏通常在.pro文件中使用配置变量指定no_keywords时使用,但即使没有指定no_keywords,也可以使用该宏。

            CONFIG += no_keywords

              【6】Q_SET_OBJECT_NAME(Object)

              此宏为对象分配objectName"Object".。
              不管对象是否是一个指针,宏本身都能计算出来。

              See also QObject::objectName().

                【7】Q_OBJECT

                Q_OBJECT宏必须出现在类定义的私有部分中,该类定义声明其自己的信号和插槽,或使用Qt的元对象系统提供的其他服务。

                在这里插入图片描述

                注意:此宏要求该类是QObject的一个子类。
                使用Q_GADGET而不是Q_OBJECT来启用元对象系统对非QObject子类的类中的枚举的支持。

                【8】Q_GADGET

                Q_GADGET宏是Q_OBJECT宏的一个较轻的版本,用于那些不继承自QObject,但仍然希望使用QMetaObject提供的一些反射功能的类。就像Q_OBJECT宏一样,它必须出现在类定义私有部分中

                Q_GADGET使类成员静态元对象(staticMetaObject)可用。QMeteObject类型为属性对象,提供对使用Q_ENUMS声明的枚举的访问。

                【9】Q_EMIT

                当您想要使用具有第三方信号/插槽机制的Qt信号和插槽时,请使用此宏来替换用来发射信号的emit关键字
                该宏通常在.pro文件中使用配置变量指定no_keywords时使用,但即使没有指定no_keywords,也可以使用该宏。

                  CONFIG += no_keywords

                  在这里插入图片描述

                  【10】事件过滤器eventFilte函数

                  原型

                  [virtual] bool QObject::eventFilter(QObject *watched, QEvent *event)

                    如果此对象已作为被监视对象的事件过滤器安装,则会过滤事件。
                    在重新实现此函数中,如果要过滤出该事件,即停止进一步处理该事件,则返回true;否则返回false。

                    Example:

                    
                    
                    
                      class MainWindow : public QMainWindow
                      {
                      public:
                          MainWindow();//公共成员函数
                      protected://保存成员函数
                          bool eventFilter(QObject *obj, QEvent *ev) override;
                      private:
                          QTextEdit *textEdit;//文本编辑对象
                      };
                      MainWindow::MainWindow()//构造函数
                      {
                          textEdit = new QTextEdit;//创建文本编辑空间
                          setCentralWidget(textEdit);//设置中央小部件
                          textEdit->installEventFilter(this);//安装事件过滤器对本对象指针
                      }
                      bool MainWindow::eventFilter(QObject *obj, QEvent *event)
                      {
                          if (obj == textEdit)
                           {//是对文本对象的操作
                              if (event->type() == QEvent::KeyPress)
                               {//按压
                                  QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);//事件强制类型转化为按键使能对象
                                  qDebug() << "Ate key press" << keyEvent->key();
                                  return true;
                              } 
                              else 
                              {
                                  return false;
                              }
                          } 
                          else 
                          {
                              // 将事件传递给父类
                              return QMainWindow::eventFilter(obj, event);
                          }
                      }
                    • 1
                    • 2
                    • 3
                    • 4
                    • 5
                    • 6
                    • 7
                    • 8
                    • 9
                    • 10
                    • 11
                    • 12
                    • 13
                    • 14
                    • 15
                    • 16
                    • 17
                    • 18
                    • 19
                    • 20
                    • 21
                    • 22
                    • 23
                    • 24
                    • 25
                    • 26
                    • 27
                    • 28
                    • 29
                    • 30
                    • 31
                    • 32
                    • 33
                    • 34
                    • 35
                    • 36
                    • 37
                    • 38

                    注意,在上面的示例中,未处理的事件被传递给基类的eventFilter()函数,因为基类可能为了自己的内部目的重新实现了eventFilter()

                    大型项目举例

                    /*******************************************************************************************
                     * *函数:eventFilter(QObject *watched, QEvent *event)
                     * *功能:主控界面-》长按按钮 进入对应功能【系统开发、治疗模式HD、回血、清洗,单超】【涉及跟控制系统的通信】
                     * *参数:watched:匹配组件           event:事件
                     * *返回值:true 或者 flase
                     * *调用:
                    ******************************************************************************************/
                    bool MainWindow::eventFilter(QObject *watched, QEvent *event)
                    {
                        if(watched == ui->widget_7)//治疗时间小部件
                        {
                            if(event->type() == QEvent::Paint)//更新ui上时间
                            {
                                int total_time = data_lib->Get_Value(278).split(":").at(0).toInt()*60+data_lib->Get_Value(278).split(":").at(1).toInt();
                                int left_time = data_lib->Get_Value(279).split(":").at(0).toInt()*60+data_lib->Get_Value(279).split(":").at(1).toInt();
                                float percent = 1.0*left_time/total_time;
                                QPainter painter(ui->widget_7);
                                painter.setRenderHints(QPainter::Antialiasing, true);//设置给定的渲染提示
                                QPen pen = painter.pen();
                                if (isIsoData == false) //非单超数据显示为蓝色
                                {
                                    pen.setColor("#0EA1B1");//设置小部件的颜色
                                }
                                else
                                {
                                    pen.setColor("#FF8700");//单超数据显示为橙色
                                }
                                pen.setWidth(6);//宽度
                                painter.setPen(pen);
                                QRect rect(26,21,112,112);
                                painter.drawArc(rect,-90*16,percent*360*16);//圆弧
                                return true;
                            }
                            else
                            {
                                return false;
                            }
                        }
                        else if(watched == ui->PB_win) //系统开发
                        {
                            if(event->type() == QEvent::MouseButtonPress)//按压
                            {
                                if(data_lib->cur_win!=WIN_MAINTE && data_lib->cur_win!=WIN_OFFLINE)//不是治疗模式&&离线模式
                                {
                                    PB_timer.start(4000);//4s定时
                                    return true;//返回真
                                }
                                else
                                {
                                    return false;
                                }
                            }
                            else if(event->type() == QEvent::MouseButtonRelease)//松开
                            {
                                PB_timer.stop();//停止4s定时
                                if(longpress == 1)
                                {
                                    Win_Change(WIN_DEVELOP);//4s后进入系统开发
                                    longpress = 0;
                                }
                                return true;
                            }
                            else
                            {
                                return false;
                            }
                        }
                        else if(watched == ui->PB_treatment)//治疗模式HD
                        {
                            if(event->type() == QEvent::MouseButtonPress)
                            {
                                PB_timer.start(2000);//2s定时器
                            }
                            else if(event->type() == QEvent::MouseButtonRelease)
                            {
                                PB_timer.stop();
                                if(longpress == 1)
                                {
                                    if(ui->PB_treatment->isEnabled())
                                    {
                                        data_lib->SendToControl(TREATMENT_HD);//发送到控制-》 治疗模式:0x01
                                    }
                                    longpress = 0;
                                }
                            }
                        }
                        else if(watched == ui->PB_bloodreturn)//回血
                        {
                            if(event->type() == QEvent::MouseButtonPress)
                            {
                                PB_timer.start(2000);//2s
                            }
                            else if(event->type() == QEvent::MouseButtonRelease)
                            {
                                PB_timer.stop();
                                if(longpress == 1)
                                {
                                    if(ui->PB_bloodreturn->isEnabled())
                                    {
                                        data_lib->SendToControl(BLOOD_RETURN);//向控制发送-》回血:0x03
                                    }
                                    longpress = 0;
                                }
                            }
                        }
                        else if(watched == ui->PB_rinse)//清洗
                        {
                            if(event->type() == QEvent::MouseButtonPress)
                            {
                                PB_timer.start(2000);//2s
                            }
                            else if(event->type() == QEvent::MouseButtonRelease)
                            {
                                PB_timer.stop();
                                if(longpress == 1)
                                {
                                    if(VERSION == 1)//正式版本
                                    {
                                        if(ui->PB_rinse->isEnabled())
                                        {
                                            data_lib->SendToControl(RINSE);//发送到控制-》清洗:0x04
                                        }
                                    }
                                    else//调试版本
                                    {
                                        if(data_lib->cur_win == WIN_RINSE)
                                        {
                                            Win_Change(WIN_MAIN);//显示主界面
                                        }
                                        else //不是清洗界面
                                        {
                                            Win_Change(WIN_RINSE);//显示清洗界面
                                            data_lib->SendToControl(RINSE);//发送到控制-》清洗:0x04
                                        }
                                    }
                                    longpress = 0;
                                }
                            }
                        }
                        else if(watched == ui->PB_HD)//单超
                        {
                            if(event->type() == QEvent::MouseButtonPress)
                            {
                                PB_timer.start(2000);//2s
                            }
                            else if(event->type() == QEvent::MouseButtonRelease)
                            {
                                PB_timer.stop();
                                if(longpress == 1)
                                {
                                    if(ui->PB_HD->isEnabled())
                                    {
                                        data_lib->SendToControl(TREATMENT_HD);//发送到控制-》治疗模式HD:0x01
                                    }
                                    longpress = 0;
                                }
                            }
                        }
                        else if(watched == ui->PB_Supply)//供液
                        {
                            if(event->type() == QEvent::MouseButtonPress)//按压
                            {
                                PB_timer.start(2000);//2s
                            }
                            else if(event->type() == QEvent::MouseButtonRelease)//松开
                            {
                                PB_timer.stop();
                                if(longpress == 1)
                                {
                                    if(ui->PB_Supply->isEnabled())//供液可按
                                    {
                                        data_lib->SendToControl(SUPPLY);//发送到控制-》供液:0x07
                                    }
                                    longpress = 0;
                                }
                            }
                        }
                        else if(watched == ui->PB_clamp)                                 //静脉夹开关
                        {
                            if(ui->PB_clamp->isEnabled())//静脉夹可按
                            {
                                if(event->type() == QEvent::MouseButtonPress)//按压
                                {
                                    data_lib->SendToControl(CLAMP_SWITCH_DOWN);//发送到控制-》静脉夹按下:0x0D
                                }
                                else if(event->type() == QEvent::MouseButtonRelease)//松开
                                {
                                    data_lib->SendToControl(CLAMP_SWITCH_UP);//发送到控制-》静脉夹松开:0x6A
                                }
                            }
                        }
                        return QMainWindow::eventFilter(watched,event);//将事件传递给父类
                    }
                    • 1
                    • 2
                    • 3
                    • 4
                    • 5
                    • 6
                    • 7
                    • 8
                    • 9
                    • 10
                    • 11
                    • 12
                    • 13
                    • 14
                    • 15
                    • 16
                    • 17
                    • 18
                    • 19
                    • 20
                    • 21
                    • 22
                    • 23
                    • 24
                    • 25
                    • 26
                    • 27
                    • 28
                    • 29
                    • 30
                    • 31
                    • 32
                    • 33
                    • 34
                    • 35
                    • 36
                    • 37
                    • 38
                    • 39
                    • 40
                    • 41
                    • 42
                    • 43
                    • 44
                    • 45
                    • 46
                    • 47
                    • 48
                    • 49
                    • 50
                    • 51
                    • 52
                    • 53
                    • 54
                    • 55
                    • 56
                    • 57
                    • 58
                    • 59
                    • 60
                    • 61
                    • 62
                    • 63
                    • 64
                    • 65
                    • 66
                    • 67
                    • 68
                    • 69
                    • 70
                    • 71
                    • 72
                    • 73
                    • 74
                    • 75
                    • 76
                    • 77
                    • 78
                    • 79
                    • 80
                    • 81
                    • 82
                    • 83
                    • 84
                    • 85
                    • 86
                    • 87
                    • 88
                    • 89
                    • 90
                    • 91
                    • 92
                    • 93
                    • 94
                    • 95
                    • 96
                    • 97
                    • 98
                    • 99
                    • 100
                    • 101
                    • 102
                    • 103
                    • 104
                    • 105
                    • 106
                    • 107
                    • 108
                    • 109
                    • 110
                    • 111
                    • 112
                    • 113
                    • 114
                    • 115
                    • 116
                    • 117
                    • 118
                    • 119
                    • 120
                    • 121
                    • 122
                    • 123
                    • 124
                    • 125
                    • 126
                    • 127
                    • 128
                    • 129
                    • 130
                    • 131
                    • 132
                    • 133
                    • 134
                    • 135
                    • 136
                    • 137
                    • 138
                    • 139
                    • 140
                    • 141
                    • 142
                    • 143
                    • 144
                    • 145
                    • 146
                    • 147
                    • 148
                    • 149
                    • 150
                    • 151
                    • 152
                    • 153
                    • 154
                    • 155
                    • 156
                    • 157
                    • 158
                    • 159
                    • 160
                    • 161
                    • 162
                    • 163
                    • 164
                    • 165
                    • 166
                    • 167
                    • 168
                    • 169
                    • 170
                    • 171
                    • 172
                    • 173
                    • 174
                    • 175
                    • 176
                    • 177
                    • 178
                    • 179
                    • 180
                    • 181
                    • 182
                    • 183
                    • 184
                    • 185
                    • 186
                    • 187
                    • 188
                    • 189
                    • 190
                    • 191
                    • 192
                  • 相关阅读:
                    群、循环群、交换群
                    Android如何实现轮播效果:ViewFlipper 和 ViewAnimator
                    C++:C++模板(函数模板与类模板的使用)
                    Java之流程控制(5)
                    微信小程序的生命周期概览
                    React高阶组件(Higher-Order Components, HOCs)
                    2023年【汽车驾驶员(中级)】报名考试及汽车驾驶员(中级)证考试
                    MyBatis-Plus生成sql语句时怎么知道表名和表的字段名,表的主键名的
                    【CMake】顶层 CMakeList.txt 常用命令总结
                    LCR 101. 分割等和子集——力扣——背包问题、动态规矩
                  • 原文地址:https://blog.csdn.net/m0_45463480/article/details/124965812