
进程肯定不会产生了。Qt的信号槽是个很复杂的机制,哥大致给你介绍一下Qt的信号槽既可以同步触发,也可以异步触发。当你进行connect的时候,实际上还有第五个参数(可以自己看SDK的介绍)。如果说是默认的,那么要看信号和槽是否属于同一个线程(这里,你可以简单理解为是否是同一个类),然后根据connect的第五个属性来判断是否是同步还是异步。比如BlockingQueuedConnection模式,就会出现你说的多次触发信号阻塞问题,他只有等到上一个触发完成才能继续。槽函数不会产生新线程,他是决定了槽函数声明在哪个线程中,如果默认情况下,在同一个线程里面是同步的,你此时可以理解为普通调用,如果在不同线程里面,槽函数运行的线程通常是异步调用,但是还有一个所谓的事件中心一直run着在处理,就是一个信号队列,没触发一个信号就入队列,先进先出。
就是要在函数里发射信号
emit mySignal(int)类似这样的句子被执行到了信号就会被发射,与信号相关的槽就会被调用
当然在发射信号前必须先将信号和槽函数用connect函数连接起来
比如现在有个槽函数为
void mySlot(int a)
{
}
并且已经与mySignal(int) 连接起来了
当程序在某个地方执行到 emit mySignal(4),这样类型的句子时mySlot()就会被调用4就被当成参数传递给了mySlot(int)就好像直接调用了mySlot(4)一样
有时我们展示了一个列表, 并想提供查看某项列表的详细内容, 我们会在列表项的末端加一个查看按钮, 这时我们如何在按按钮的时候得知这是那一项呢 这时就需要带参数的信号, 信号是可以带参数的, 参数会在信号发送时携带, 并传递给接收此信号的槽
from PyQt4 import QtGui, QtCore
class MyButton(QtGuiQPushButton):
myclicked = QtCorepyqtSignal(int)
def __init__(self, _id, args, kwargs):
QtGuiQPushButton__init__(self, args, kwargs)
self_id = _id
selfconnect(self, QtCoreSIGNAL("clicked()"), selfemitMyclicked)
def emitMyclicked(self):
selfmyclickedemit(self_id)
app = QtGuiQApplication([])
w = QtGuiQWidget()
wresize(100, 100)
def showMsg(_id):
QtGuiQMessageBoxinformation(w, u"信息", u"查看 %d" % _id)
btn = MyButton(1, u"查看1", w)
wconnect(btn, QtCoreSIGNAL("myclicked(int)"), showMsg)
btn2 = MyButton(2, u"查看2", w)
btn2move(0, 30)
wconnect(btn2, QtCoreSIGNAL("myclicked(int)"), showMsg)
wshow()
appexec_()
上面例子可以看出, QObjectemit 发送带参数的信号时要携带参数 当然上面例子也可以用下面方式来写
from PyQt4 import QtGui, QtCore
class MyButton(QtGuiQPushButton):
def __init__(self, _id, args, kwargs):
self_id = _id
QtGuiQPushButton__init__(self, args, kwargs)
selfconnect(self, QtCoreSIGNAL("clicked()"), selfemitClicked)
def emitClicked(self):
selfemit(QtCoreSIGNAL("myclicked(int)"), self_id)
app = QtGuiQApplication([])
w = QtGuiQWidget()
wresize(100, 100)
def showMsg(_id):
QtGuiQMessageBoxinformation(w, u"信息", u"查看 %d" % _id)
btn = MyButton(1, u"查看1", w)
wconnect(btn, QtCoreSIGNAL("myclicked(int)"), showMsg)
btn2 = MyButton(2, u"查看2", w)
btn2move(0, 30)
wconnect(btn2, QtCoreSIGNAL("myclicked(int)"), showMsg)
wshow()
appexec_()
可以的;前面需要添加特定的信号槽标识符
class MyClass : public QObject {// 这个宏一定要添加,否则无法使用信号槽
Q_OBJECT
public:
MyClass(){}
void publicTestFunc() { emit signalTest(110);}
//-- 下面函数是自动的信号函数,无实体,定义即可 --//
signals:
void signalTest(int nCnt); // 可带参数,可不带
//-- 下面函数是自定义的槽函数,需要写实现方法 --//
slots:
void sltTestFunc(int nCnt) {
qDebug() << "connect the signal: " << nCnt;
}
};
// 然后使用
MyClass test1 = new MyClass();
MyClass test2 = new MyClass();
connect(test1, SIGNAL(signalTest(int)), test2, SLOT(sltTestFunc(int)));
// 然后用test1发送信号,test2接收
自定义信号和槽
signals:
SendText(QString text);
privite slots:
ReciveText(QString text);
界面类的构造函数中connect信号和槽。
按钮的点击处理函数中获取lineEdit的内容,并作为信号SendText的参数。
然后发射信号 emit SendText(text);
槽函数SendText中 *** 作文本编辑器。
对,信号可以自己定义
而信号一般是只声明函数体,关键是其参数
信号一般是用来传参或者是一种逻辑的调用者
信号的发射可以在你自定义的函数中
就比如我们继承了一个widget,要重写mousePressEvent
于是我们就可以自己定义一个signal, MyClicked( const QPoint& pos )
然后在事件中emit( MyClicked( event->pos() ) )
不过一般clicked信号是在mouseReleaseEvent中emit的
当然这一切都必须你继承QObject以及声明Q_OBJECT了
而且你也可以把你自己的一些属性property声明至元系统
就是宏Q_PROPERTY()
这个其实很有用,举个例子
我们想知道信号发送者的某一个属性
于是我已经Connect了
然后我们就可以在对应的槽中获取
用sender()获取object对象然后调用property来获取发送者的某个属性
还是自己多运用吧
以上都我自己打的阿~ 你还有不会的可以hi我
接上一章链接部分,继续讲信号槽是如何调用的
首先看看信号是如何触发的,一般都是这么写:
emit sendertest_Signal(1);
这个emit是啥,其实啥也不是,就是一个空的define
它只是用来标记这是一个信号方便阅读,其实这个信号本身也是一个函数,只不过我们没有实现,这是语言的基础,定义了函数肯定是要实现的,那么它的实现在哪呢,答案还在moc文件内部,以之前的例子为例,它的实现是这样的
在这里将信号的参数包装成了void的数组,然后调用元对象的activate函数,如下
这一部分主要是判断信号是否有链接槽函数
之前讲过Qt4的槽函数是存储在Connection的callFunction对象,如果这个不为空就会判断为Qt4的链接方式
这种就比较简单,直接调用callFunction即可,这个callFunction是什么呢,不知道是否还记得,之前链接的时候讲过,它就是moc文件里的qt_static_metacall,如果不记得了回去看看,这里在放出
是否还记得Qt5的槽放在哪呢,它放在一个QSlotObject对象里,Connection保存的是这个对象的地址,因此通过判断这个地址是否为空就能判断是否为Qt5的调用方式
还记得之前将的QSlotObject吗,它是QSlotObjectBase的子类,为了方便再贴出来看看
这里面调用的又是 FuncType(也就是FunctionPointer<Func>)的call函数,好记得它是什么吗,就是用来判断槽函数是否为receiver成员函数的那个模板类,再贴出来看看
到此就会调用到我们的槽函数,Qt5方式的调用也就结束了
Qt信号槽在链接的时候最后一个参数代表的是链接方式,包括5中
一般用的比较多的就是AutoConnection和QueuedConnection,如果是auto的方式,调用时会判断信号所在线程和槽所在线程是否是一个线程,如果不是就是queue的方式调用,具体是这样判断的
如果是QueuedConnection,会把当前的信号包装成一个QMeCallEvent的事件,进入到事件循环来调用槽函数
2、用了QueuedConnection是不是就代表是异步了呢?
那么事件循环是怎么调用到这个函数的呢?
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)