[Qt][信号与槽][上]详细讲解

0.Q_OBJECT宏

  • Qt如果要让某个类能够使用信号槽,则必须要在类最开始的地方,写下Q_OBJECT

1.信号和槽概述

1.信号

  • 在Qt中,⽤⼾和控件的每次交互过程称为⼀个事件
    • 例如:"⽤⼾点击按钮"是⼀个事件,"⽤⼾关闭窗⼝"也是⼀个事件
  • 每个事件都会发出⼀个信号
    • 例如:⽤⼾点击按钮会发出"按钮被点击"的信号,⽤⼾关闭窗⼝会发出"窗⼝被关闭"的信号
  • 信号的本质
    • 信号是由于⽤⼾对窗⼝或控件进⾏了某些操作,导致窗⼝或控件产⽣了某个特定事件,这时Qt对应的窗⼝类会发出某个信号,以此对⽤⼾的操作做出反应
    • 因此,信号的本质就是事件
  • Qt中信号是通过什么形式呈现给使⽤者的呢?
    • 对哪个窗⼝进⾏操作,哪个窗⼝就可以捕捉到这些被触发的事件
    • 对于使⽤者来说,触发了⼀个事件就可以得到Qt框架发出的某个特定信号
    • 信号的呈现形式就是函数
      • 也就是说某个事件产⽣了,Qt框架就会调⽤某个对应的信号函数,通知使⽤者
  • 在Qt中信号的发出者是某个实例化的类对象

2.槽

  • Qt中的**所有控件都具有接收信号的能⼒,⼀个控件还可以接收多个不同的信号**

  • 对于接收到的每个信号,控件都会做出相应的响应动作

    • 按钮所在的窗⼝接收到"按钮被点击"的信号后,会做出"关闭⾃⼰"的响应动作
    • 输⼊框⾃⼰接收到"输⼊框被点击"的信号后,会做出"显⽰闪烁的光标,等待⽤⼾输⼊数据"的响应动作
  • 在Qt中,对信号做出的响应动作就称之为槽

  • 信号和槽是Qt特有的消息传输机制,它能将相互独⽴的控件关联起来

    • 例如:“按钮"和"窗⼝” 本⾝是两个独⽴的控件,点击"按钮"并不会对"窗⼝"造成任何影响。通过信号和槽机制,可以将"按钮"和"窗⼝"关联起来,实现"点击按钮会使窗⼝关闭"的效果
      请添加图片描述
  • 槽的本质

    • 槽(Slot)就是对信号响应的函数
    • 槽就是⼀个函数,与⼀般的C++成员函数是⼀样的
      • 可以定义在类的任何位置(public, protected, private)
      • 可以具有任何参数
      • 可以被重载
      • 也可以被直接调⽤(但是不能有默认参数)
    • 槽函数与⼀般的函数不同的是槽函数可以与⼀个信号关联,当信号被发射时,关联的槽函数被⾃动执⾏

3.说明

  • 信号和槽机制底层是通过函数间的相互调⽤实现的
    • 每个信号都可以⽤函数来表⽰,称为信号函数
    • 每个槽也可以⽤函数表⽰,称为槽函数
    • 例如
      • "按钮被按下"这个信号可以⽤clicked()表⽰,"窗⼝关闭"这个槽可以⽤close()表⽰,
      • 假如使⽤信号和槽机制实现:"点击按钮会关闭窗⼝"的功能,其实就是clicked()调⽤close()的效果
  • 信号函数和槽函数通常位于某个类中,和普通的成员函数相⽐,它们的特别之处在于
    • 信号函数⽤signals关键字修饰
    • 槽函数⽤public slots, protected slots, private slots修饰
    • signalsslots是Qt在C++的基础上扩展的关键字,专⻔⽤来指明信号函数和槽函数
  • 信号函数只需要声明,不需要定义(实现),⽽槽函数需要定义(实现)
    • 信号函数的定义是Qt⾃动在编译程序之前⽣成的,编写Qt应⽤程序的程序员⽆需关注
    • 这种⾃动⽣成代码的机制称为元编程(MetaProgramming)

2.信号和槽的使用

1.连接信号和槽

  • QObject类提供了⼀个静态成员函数connect(),专⻔⽤来关联指定的信号函数和槽函数
  • 函数原型
    connect(const QObject* sender, 
    		const char* signal, 
    		const QObject* receiver, 
    		const char* method,
    		Qt::ConnectionType type = Qt::AutoConnection)
    
  • 参数
    • sender:信号的发送者 -> 当前信号由哪个空间发出
    • signal:发送的信号(信号函数)
      • 要求和sender必须是匹配的
      • :如果senderQPushButton*,那么signal必须是QPushButton内置的信号(父类的信号),不能是其他类的信号
    • receiver:信号的接收者 --> 哪个对象负责处理
    • method:接收信号的槽函数 --> 这个对象该怎么处理
    • type:⽤于指定关联⽅式,默认的关联⽅式为Qt::AutoConnection通常不需要⼿动设定
  • 疑问:为什么signalmethod类型是char*
    • 这个函数声明,是旧版本的Qt的connect的函数声明
      • 此时使用要搭配SIGNALSLOT使用
      • 例如connect(button, SIGNAL(&QPushButton::clicked), this, SLOT(&Widget::close));
    • Qt5开始,对上述写法做出了简化,不再需要SIGNALSLOT了,提供了connect的重载版本,该版本中,signalmethod成了泛型参数,允许传入任意类型的指针了
      template <typename Func1, typename Func2>
      static inline QMetaObject::Connection
      connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, 
              Func1 signal,
              const typename QtPrivate::ContextTypeForFunctor<Func2>::ContextType *context, 			
              Func2 &&slot,
              Qt::ConnectionType type = Qt::AutoConnection)
      

2.查看内置信号和槽

  • 系统⾃带的信号和槽通常是通过"Qt帮助⽂档"来查询
  • 如果没有找到,可以继续去⽗类中查找
  • 28
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DieSnowK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值