admin管理员组文章数量:1794759
Qt信号槽之槽函数中获取发送信号对象——sender()
QObject::sender()
我们如何在槽函数中获取到信号的发送对象呢,使用sender()方法即可获取。但是使用此方法我们需要注意几点:
QObject *QObject::sender() const
1、使用sender()方法获取信号的发送对象,前提是槽函数是被信号触发的,而非自己调用,否则返回空(nullptr),所以我们在使用的时候最好加个非空判断; 2、通过此方法获取的对象指针仅在槽函数执行的期间有效; 3、如果在此期间,信号发送对象被销毁,或者信号与槽函数已经断开,此对象指针将无效; 4、此方法虽然违背了面向对象的模块化原则,但是当多个信号连接同一个槽函数的时候,可以通过此方法获取到发送信号的对象,根据这个对象来判断当前是哪个信号触发的槽函数,当我们多个信号绑定一个槽函数的时候,一般是需要根据信号的不同来做不同的操作,所以这里可以获取到实际发生信号的对象,那我们就知道是哪个信号,然后就可以去处理了。如下方代码,如果有多个信号连接到onDealWork槽函数,我们可以根据objectName()属性/对象的类型进行区分来处理不同的工作,其他区分的方式也都可以,具体看实际情况。
通过对象的objectName
void onDealWork() { QObject* obj = sender(); if(obj->objectName() == "Btn") { // todo; } else if(obj->objectName() == "Label") { // todo; } else if(obj->objectName() == "Edit") { // todo; } }通过对象的类型
void onDealWork() { QObject* obj = sender(); QObject* obj = sender(); QPushButton* pBtn = dynamic_cast<QPushButton*>(obj); if (pBtn != nullptr) { // todo; } QLabel* pLabel = dynamic_cast<QLabel*>(obj); if (pLabel != nullptr) { // todo; } } 5、当我们使用 Qt::DirectConnection 类型作为信号槽的连接方式,且槽函数调用的线程不同于信号发送对象的线程,这个时候sender()方法返回的QObject对象指针是无效的,这种场景是不可以使用此方法来获取信号发送对象的。 大家可以使用下方代码进行测试,在槽函数中使用sender()获取的对象指针实际为nullptr,所以大家最好是获取到指针之后加上非空判断。 实际上使用Qt::DirectConnection连接方式,信号的触发和槽函数执行都是在同一个线程中,大家可以使用下方代码查看线程id,Qt::HANDLE mainId 和 Qt::HANDLE childId,使用 Qt::DirectConnection两者id一致,也就是处在同一个线程,使用 Qt::QueuedConnection或者默认不填,两者id是不一样的,表示不在同一个线程。 class Worker : public QObject { Q_OBJECT public slots: void doWork(const QString ¶meter) { Qt::HANDLE childId = QThread::currentThreadId(); QString result; QObject* obj = sender(); if (obj != nullptr) { result = sender()->objectName(); qDebug() << "current connect type is Qt::QueuedConnection"; } else { // 如果多线程情况下,信号槽使用Qt::DirectConnection这种连接方式; // 这里sender()返回空指针nullptr; qDebug() << "current connect type is Qt::DirectConnection"; } emit resultReady(result); } signals: void resultReady(const QString &result); }; class Controller : public QObject { Q_OBJECT QThread workerThread; public: Controller() { this->setObjectName("123"); Worker *worker = new Worker; worker->moveToThread(&workerThread); connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater); // 如果使用此方式,在多线程的时候,默认是Qt::QueuedConnection; //connect(this, &Controller::operate, worker, &Worker::doWork); connect(this, &Controller::operate, worker, &Worker::doWork, Qt::DirectConnection); connect(worker, &Worker::resultReady, this, &Controller::handleResults); workerThread.start(); } ~Controller() { workerThread.quit(); workerThread.wait(); } public slots: void handleResults(const QString & result){ qDebug() << result; } signals: void operate(const QString &); }; // 测试代码; void test() { Qt::HANDLE mainId = QThread::currentThreadId(); Controller* control = new Controller(); emit control->operate("test"); }下图中是使用VS调试过程中sender()返回的值为空(nullptr)。
尾
Qt训练营内容(一期) 开始啦 ,更多详细的文章有兴趣的小伙伴可以点击看一看哈,里面有更多优质的内容等着你!也可以加群 861353824 一起交流哈!
版权声明:本文标题:Qt信号槽之槽函数中获取发送信号对象——sender() 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1686490345a73377.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论