QT 信号与槽connect
QT 信号与槽connect
QT中信号与槽的连接使用的connect
函数是一个静态函数,在类QObject
中定义。这里说的是QT5
环境下。更详细的介绍可以看这里http://www.devbean.net/2012/12/how-qt-signals-and-slots-work-qt5/
本文由乌合之众 lym瞎编,欢迎转载 blog.cnblogs.net/oloroso
本文由乌合之众 lym瞎编,欢迎转载 my.oschina.net/oloroso
connect函数调用几个限制
-
1. 信号的发送者必须是
QObject
的派生类对象。不然会出现error: invalid conversion from 'XXX*' to 'const QObject*' [-fpermissive]...
的错误。 -
2. 回调槽函数的对象必须是
QObject
的派生类对象。不然会出现error: no matching function for call to 'QObject::connect(XXX*,
的错误。这里要注意一点,信号函数无论存在与否,都不会报错的。但是如果信号的发送者是NULL
,那么会在运行的时候提示QObject::connect: Cannot connect (null)::信号函数() to 接收者::槽函数()
的问题。 -
对于
1,2
两点,在connect
函数调用的时候强转类型也可以通过编译,但是运行的时候会提示No such slot QObject::
的问题。 -
3. 槽函数所在的类的定义中必须添加宏
Q_OBJECT
,不然会出现QObject::connect: No such slot ...
的错误。这里必须和第
2
点联系起来,如果添加了Q_OBJECT
宏的类不是从QObject
派生的,moc
生成中间文件的时候会报错Error: Class contains Q_OBJECT macro but does not inherit from QObject
。如果添加了
Q_OBJECT
宏之后编译出现了undefined reference to ‘vtable for...
的错误,请删除build
目录下的Makefile
文件,再重新生成。 -
4. 信号函数的
signals
修饰和槽函数的slots
修饰其实是必须的。虽然生成的中间代码中会去除掉。 - 5.如果槽函数是on_控件名_信号名那么不需要主动调用connnect进行连接。
问题 | 原因 |
---|---|
error: no matching function for call to 'QObject::connect(XXX*, |
信号的发送者和接受者必须是QObject 的派生类对象。 |
QObject::connect: No such slot ... |
满足面的条件后,还必须满足槽函数所在类的定义中添加(使用)了Q_OBJECT 宏 |
Error: Class contains Q_OBJECT macro but does not inherit from QObject |
添加了Q_OBJECT 宏的类不是从QObject 派生的 |
undefined reference to ‘vtable for... |
这是在添加了Q_OBJECT 宏之后编译出现,原因是没有更新Makefile 文件。请删除build 目录下的Makefile 文件,再使用qmake 重新生成。 |
No matching signal for on_XXXXX_XXXXX() |
槽函数是on_控件名_信号名形式,又显示的调用了connect进行连接,就会在运行时出现这个,但是没有什么关系。 |
connect函数代码
connect是一个模板函数,但是对参数的类型是有要求的。
这个函数的返回值是QMetaObject::Connection
类型的。
1 //Connect a signal to a pointer to qobject member function 2 //连接一个信号到 qobject 成员函数的指针 3 4 template <typename Func1, typename Func2> 5 static inline QMetaObject::Connection connect( 6 const typename QtPrivate::FunctionPointer<Func1>::Object *sender, 7 Func1 signal, 8 const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, 9 Func2 slot,Qt::ConnectionType type = Qt::AutoConnection 10 ) 11 { 12 typedef QtPrivate::FunctionPointer<Func1> SignalType; 13 typedef QtPrivate::FunctionPointer<Func2> SlotType; 14 15 //检查信号类是否有Q_OBJECT宏 16 Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value, 17 "No Q_OBJECT in the class with the signal"); 18 19 //compilation error if the arguments does not match. 20 //如果参数不匹配的编译错误。 21 //槽函数需要的参数比信号函数提供多。 22 Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount), 23 "The slot requires more arguments than the signal provides."); 24 //信号函数和槽函数的参数不是兼容的。 25 Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value), 26 "Signal and slot arguments are not compatible."); 27 //信号函数返回类型是槽函数的不兼容的返回类型。 28 Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value), 29 "Return type of the slot is not compatible with the return type of the signal."); 30 31 const int *types = 0; 32 if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection) 33 types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types(); 34 35 //QObject::connectImpl是用于执行连接的私有内部函数。 36 //槽函数的包装器,用于辅助调用该槽函数。 37 return connectImpl(sender, reinterpret_cast<void **>(&signal), 38 receiver, reinterpret_cast<void **>(&slot), 39 new QtPrivate::QSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value, 40 typename SignalType::ReturnType>(slot), 41 type, types, &SignalType::Object::staticMetaObject); 42 }