Qt 6:一个超级简单例子熟悉信号、槽 机制

//main.cpp
#include "Counter.h"
int main(void){
    Counter counter;
    QObject::connect(&counter,&Counter::Is_Signal,&counter,&Counter::Is_Slots);
    while(1) {
    int num;
    std::cout<<"enter 1 to emit the sign"<<std::endl;
    std::cin>>num;
    if (num==1){
    emit counter.Is_Signal(1);
        std::cout<<std::endl;
}}
}
//Counter.h
#include "QObject"
#include <iostream>
class Counter : public QObject
{
    Q_OBJECT

public Q_SLOTS:
    void Is_Slots(int value){
        std::cout<<"Slot function is done!";
    };
    signals:
    void Is_Signal(int value);

};

借鉴并且化用了官网的例子。官网
但是不够直观,我改了一下,只需要这两个文件。
这样就实现了一个基本的Qt信号机制。
最基本需要注意的点。
1.实现信号机制的类必须继承自 QObject ,而且下面要添加这个 Q_OBJECT 。里面定义了 QMetaObject 等一些基本的属性和方法。
2.
定义Slot 的类的方法前要加 public slots:,声明一下。
定义signals 的类的方法前 加 signals:。注意这里不是 public signals:
我们顺着 signals 的宏定义一直找到源头:

# define Q_SLOTS QT_ANNOTATE_ACCESS_SPECIFIER(qt_slot)
# define Q_SIGNALS public QT_ANNOTATE_ACCESS_SPECIFIER(qt_signal)
...
 define slots Q_SLOTS
...
define signals Q_SIGNALS

原来这里已经有了一个public!

slots 函数需要实现(就是写函数里都有啥),但是signal函数不需要,只用声明一下就好了。
实际上我们声明一个signal函数只是为了调用一下它,它根本不需要实现。
4.

 template <typename Func1, typename Func2>
    static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
                                     const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot,
                                     Qt::ConnectionType type = Qt::AutoConnection)

connect函数中的参数 signal和 slot 应该输入 &类名::函数名字 。而不是
&对象名::函数名字。 (看作类的静态函数)
看下GDB的调试:

//main函数
(gdb) p counter
$1 = (Counter) {<QObject> = {<No data fields>}, static staticMetaObject = {d = {superdata = {direct = 0x7ffff709a140 <QObject::staticMetaObject>}, stringdata = 0x555555559060 <qt_meta_stringdata_Counter>, data = 0x5555555590c0 <qt_meta_data_Counter>, static_metacall = 0x55555555733a <Counter::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)>, relatedMetaObjects = 0x0, metaTypes = 0x55555555ba60 <qt_incomplete_metaTypeArray<qt_meta_stringdata_Counter_t, QtPrivate::TypeAndForceComplete<Counter, std::integral_constant<bool, true> >, QtPrivate::TypeAndForceComplete<void, std::integral_constant<bool, false> >, QtPrivate::TypeAndForceComplete<int, std::integral_constant<bool, false> >, QtPrivate::TypeAndForceComplete<void, std::integral_constant<bool, false> >, QtPrivate::TypeAndForceComplete<int, std::integral_constant<bool, false> > >>, extradata = 0x0}}}
(gdb) p &counter
$2 = (Counter *) 0x7fffffffe380
(gdb) p counter.Is_Signal
$3 = {void (Counter * const, int)} 0x555555557576 <Counter::Is_Signal(int)>
(gdb) p counter.Is_Slots
$4 = {void (Counter * const, int)} 0x55555555776e <Counter::Is_Slots(int)>

//connect函数内部
(gdb) p sender
$5 = (const QtPrivate::FunctionPointer<void (Counter::*)(int)>::Object *) 0x7fffffffe380
(gdb) p signal
$6 = (void (Counter::*)(Counter * const, int)) 0x555555557576 <Counter::Is_Signal(int)>
(gdb) p receiver
$7 = (const QtPrivate::FunctionPointer<void (Counter::*)(int)>::Object *) 0x7fffffffe380
(gdb) p slot
$9 = (void (Counter::*)(Counter * const, int)) 0x55555555776e <Counter::Is_Slots(int)>

除了sender和receiver有变化外,其他没有变化。最后调用了这个函数。
static QMetaObject::Connection connectImpl(const QObject *sender, void **signal,
                                               const QObject *receiver, void **slotPtr,
                                               QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type,
                                               const int *types, const QMetaObject *senderMetaObject);

看出counter对象里多了一大堆东西来自最开始前面那个宏 Q_OBJECT ,可以看出来很重要。
里面

  1. 调用Signal 函数 的时候,我们这里写了个 emit 表示“发出了一个信号”,实际上emit这个宏什么也没有,可以不写。但是习惯上带上。
  2. 调用Is_Signal 函数的时候,会来到Qt引擎生成的一个文件里。在debug文件里 有个autogen结尾的文件夹,那个就是自动生成的。里面还有个文件夹里有这个文件,里面出现了Qt 自动帮我们补全的Counter::Is_Signal真面目了!看到里面调用了 QMetaObject::activate,Qt在背后帮我们做了整个过程。
//moc_Counter.cpp
Created by: The Qt Meta Object Compiler version 68 (Qt 6.2.2)
...
// SIGNAL 0
void Counter::Is_Signal(int _t1)
{
    void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
    QMetaObject::activate(this, &staticMetaObject, 0, _a);
}

7.那么这个activate函数是啥呢?是这个

//qobjectdefs.h
static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv);

没功夫再往下面看了…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值