日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【探究】信号槽到底能不能有返回值?

發(fā)布時間:2023/12/10 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【探究】信号槽到底能不能有返回值? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

【探究】信號槽到底能不能有返回值?

前言

Qt信號槽到底可不可以有返回值呢?問了下身邊的同事,有的人說可以,有的人說不可以。在實際項目中,確實沒看到過有人使用帶返回值的信號槽,可以說存在感很低。平時大家工作也比較忙,所以也沒有時間去較真信號槽到底能不能有返回值。今天就一起帶大家較真一下,看一看信號槽能否有返回值。如果可以有返回值,那么又有哪些限制導(dǎo)致大家都不用它呢?

提示:本文代碼略多,但是都很簡單,請耐心閱讀。

上代碼

新建一個Qt Widgets Application,在Qt為我們生成的主窗口.h文件中,添加信號槽的聲明,分別是

  • 信號QString sigCurrentTime(),用于獲取當(dāng)前時間的信號
  • 槽QString slotCurrentTime(),用于獲取當(dāng)前時間的槽

完整代碼如下:

#ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> namespace Ui { class MainWindow; }class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();signals:// 用于獲取當(dāng)前時間的信號QString sigCurrentTime();private slots:// 用于獲取當(dāng)前時間的槽QString slotCurrentTime();private:Ui::MainWindow *ui; };#endif // MAINWINDOW_H

在.cpp文件中,建立信號槽連接,實現(xiàn)槽函數(shù),發(fā)送信號并打印返回值。完整代碼如下:

#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDateTime> #include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);connect(this, SIGNAL(sigCurrentTime()), this, SLOT(slotCurrentTime()));qDebug() << "Current Time:" << sigCurrentTime(); }MainWindow::~MainWindow() {delete ui; }QString MainWindow::slotCurrentTime() {return QDateTime::currentDateTime().toString("yyyyMMdd hh:mm:ss"); }

代碼很簡單,運行結(jié)果如下:

答案很明確:信號槽可以有返回值。 即槽的返回值會傳遞給信號,作為信號的返回值返回。
得出上述結(jié)論只是第一步。

下面開始我們的第二問:
是否所有情況下,信號槽返回值都可以正常工作呢?

不同機(jī)制下的運行情況

在確保信號槽正常連接,并能夠成功發(fā)送接收的前提下,影響信號槽工作的因素就只有在connect信號槽時指定的、信號槽的連接方式。
我們知道信號槽的連接方式有以下幾種:

  • AutoConnection,
  • DirectConnection,
  • QueuedConnection,
  • BlockingQueuedConnection,
  • UniqueConnection

嚴(yán)格來說,最后一個UniqueConnection是用來保證信號槽一對一連接的,從實現(xiàn)機(jī)制上并不算是一種連接方式。所以我們依次測試前四種連接方式,得到了不同的結(jié)果。

  • AutoConnection

默認(rèn)連接方式,輸出和前面的輸出相同。

  • DirectConnection

即代碼改成:

connect(this, SIGNAL(sigCurrentTime()), this, SLOT(slotCurrentTime()), Qt::DirectConnection);

此種為直接連接方式,相當(dāng)于函數(shù)調(diào)用,輸出結(jié)果為

可以看到,返回值可以正常返回。

  • QueuedConnection

即代碼改成:

connect(this, SIGNAL(sigCurrentTime()), this, SLOT(slotCurrentTime()), Qt::QueuedConnection);

此種為異步消息方式連接,用于將消息發(fā)向具有消息循環(huán)的線程,以消息的方式傳遞信號,信號槽既可以在同一個線程,也可以在不同的線程。這里在主線程進(jìn)行了測試,輸出結(jié)果為

線程間信號槽返回值測試結(jié)果相同。可以看到異步消息方式,信號槽返回值無法工作。

  • BlockingQueuedConnection

此種方式用于多線程環(huán)境下,一個線程向另外一個線程發(fā)送信號,并阻塞等待槽執(zhí)行完成。
下面是多線程的測試代碼,添加了一個新的QObject子類:ObjectInSubThread,用于在子線程中運行。代碼如下(想要直接看結(jié)果的同學(xué)可直接跳過):

ObjectInSubThread.h頭文件

#ifndef OBJECTINSUBTHREAD_H #define OBJECTINSUBTHREAD_H#include <QObject>class ObjectInSubThread : public QObject {Q_OBJECT public:explicit ObjectInSubThread(QObject *parent = nullptr);private slots:// 用于獲取當(dāng)前時間的槽QString slotCurrentTime(); };#endif // OBJECTINSUBTHREAD_H

ObjectInSubThread.cpp實現(xiàn)文件

#include "ObjectInSubThread.h" #include <QDateTime>ObjectInSubThread::ObjectInSubThread(QObject *parent) : QObject(parent) {}QString ObjectInSubThread::slotCurrentTime() {return QDateTime::currentDateTime().toString("yyyyMMdd hh:mm:ss"); }

同時修改mainwindow類的代碼:

mainwindow.h

#ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include "ObjectInSubThread.h" #include <QThread>namespace Ui { class MainWindow; }class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();signals:// 用于獲取當(dāng)前時間的信號QString sigCurrentTime(); private:Ui::MainWindow *ui;ObjectInSubThread *m_obj_in_subthread; /* 子線程中的對象 */QThread m_sub_thread; /* 子線程 */ }; #endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDateTime> #include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow), m_obj_in_subthread(0) {ui->setupUi(this);// 創(chuàng)建子線程對象m_obj_in_subthread = new ObjectInSubThread;// 移動到子線程中m_obj_in_subthread->moveToThread(&m_sub_thread);// 啟動子線程消息循環(huán)m_sub_thread.start();// 建立信號槽連接connect(this, SIGNAL(sigCurrentTime()), m_obj_in_subthread, SLOT(slotCurrentTime()), Qt::BlockingQueuedConnection);qDebug() << "Current Time:" << sigCurrentTime(); }MainWindow::~MainWindow() {delete ui;m_sub_thread.quit();m_sub_thread.wait();if (m_obj_in_subthread) delete m_obj_in_subthread; }

輸出結(jié)果:

表明信號槽返回值功能可以正常工作。

綜上所述:

從不同的信號槽連接機(jī)制的角度看,不管是在多線程還是單線程,只要是異步非阻塞方式連接的信號槽,都無法獲取返回值;只要是同步阻塞方式連接的信號槽,都可以獲取返回值。
原理上也比較容易理解。非阻塞方式連接的信號槽,信號返回時,槽還沒有返回,如何將返回值傳遞回去呢,邏輯上是行不通的。只有在同步阻塞的情況下,由響應(yīng)槽先返回,將返回值傳遞給信號以后,信號再返回,這樣便實現(xiàn)了信號槽的返回值功能。

不同使用方式下的運行情況

上面講解了不同連接機(jī)制下的運行情況。在實際使用時,也有一些情況需要考慮。
比如,一個帶返回值的信號,連接到多個帶相同類型返回值的槽,最后的返回值是什么?
新建Qt Widgets Application測試,下面是測試代碼:

mainwindow.h文件

#ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>namespace Ui { class MainWindow; }class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();signals:// 用于獲取當(dāng)前時間的信號QString sigCurrentTime();private slots:// 用于獲取當(dāng)前時間的槽QString slotCurrentTime1();// 用于獲取當(dāng)前時間的槽QString slotCurrentTime2();private:Ui::MainWindow *ui; }; #endif // MAINWINDOW_H

mainwindow.cpp文件

#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDateTime> #include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);// sigCurrentTime分別連接到槽slotCurrentTime1()和槽slotCurrentTime2()connect(this, SIGNAL(sigCurrentTime()), this, SLOT(slotCurrentTime1()));connect(this, SIGNAL(sigCurrentTime()), this, SLOT(slotCurrentTime2()));qDebug() << "Current Time:" << sigCurrentTime(); }MainWindow::~MainWindow() {delete ui; }QString MainWindow::slotCurrentTime1() {return QDateTime::currentDateTime().toString("yyyyMMdd hh:mm:ss") + " slotCurrentTime1"; }QString MainWindow::slotCurrentTime2() {return QDateTime::currentDateTime().toString("yyyyMMdd hh:mm:ss") + " slotCurrentTime2"; }

如上所示,信號sigCurrentTime分別連接到了槽slotCurrentTime1()和槽slotCurrentTime2()。
輸出結(jié)果為:

可見,最后輸出結(jié)果只有一個,另外一個結(jié)果丟失或被覆蓋,這是符合邏輯的,因為返回值只能有一個,最后的結(jié)果會覆蓋前面的結(jié)果。

結(jié)語

本文從實現(xiàn)機(jī)制角度、應(yīng)用場景角度對信號槽返回值功能進(jìn)行了實驗和分析,基本涵蓋了工作中的各種使用情形,弄清楚了在不同的情況下,信號槽返回值功能的表現(xiàn)情況。一句話總結(jié)就是:

只有同步阻塞連接時才能使用信號槽返回值,且不管有幾個槽只能有一個返回值。

正是因為信號槽返回值限制太多,所以才幾乎沒有人使用。但是我們的研究沒有白費,通過研究的過程也加深了我們對信號槽機(jī)制的理解。

關(guān)于信號槽,有太多話題可以聊,后面會推出更多相關(guān)文章,敬請關(guān)注!


本文由公眾號“Qt未來工程師”原創(chuàng)首發(fā)。

總結(jié)

以上是生活随笔為你收集整理的【探究】信号槽到底能不能有返回值?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。