Qt - 发出信号时的返回值?

时间:2018-03-31 09:45:17

标签: c++ qt

如何只在发出信号时才能使函数返回值?

FileDownloader类会发出一个'下载的()'下载完成后发出信号。我想在发出下载的()信号后返回下载的数据。

QImage ImgDownloader::downloadIMG(QUrl url){
    fd = new FileDownloader(url, this);
    //????
    return QImage::fromData(fd->downloadedData());
}

编辑:为了澄清事情,downloadIMG()函数不是插槽或信号。

FileDownloader包含以下(https://wiki.qt.io/Download_Data_from_URL

中的插槽和信号
class FileDownloader : public QObject
{
 Q_OBJECT
 public:
  explicit FileDownloader(QUrl imageUrl, QObject *parent = 0);
  virtual ~FileDownloader();
  QByteArray downloadedData() const;

 signals:
  void downloaded();

 private slots:
  void fileDownloaded(QNetworkReply* pReply);

 private:
  QNetworkAccessManager m_WebCtrl;
  QByteArray m_DownloadedData;
};

我想要实现的是创建一个从QUrl [QImage func(QUrl)]返回QImage的函数。但是,我想确保在返回值之前已下载数据。 (利用下载的()信号?)

2 个答案:

答案 0 :(得分:0)

你好像很困惑。即使Qt中的信号确实可以返回值,但如果有的话,很少使用它。也就是因为它没有多大意义。

您可能想做的不是返回,而是使用信号发出图像,这样您就可以将其连接到将接收图像并对其执行操作的功能。

在这种情况下,您希望将信号声明为:

void downloaded(QImage img);

通过以下方式发出:

emit downloaded(Image::fromData(fd->downloadedData()));

或只是:

downloaded(Image::fromData(fd->downloadedData()));

因为emit只是为了便于阅读而无法做任何事情。

  

我想要实现的是创建一个返回QImage的函数   来自QUrl [QImage func(QUrl)]。但是我想确保   在返回值之前已下载数据。

这种情况发生的唯一方法是使用阻止API,但不建议在主/ GUI线程中执行此操作,因为您的应用程序似乎对操作系统没有响应。如果要在GUI中使用图像,则必须在另一个线程中执行此操作并将最终结果传递给主线程。无论如何,你仍然必须使用上面的信号声明来发射图像才能到达那里。当您连接到主线程时,Qt将检测到两个对象在不同的​​线程中运行并为您使用排队连接。

或者您可以执行在主线程中定期运行的非阻塞实现,而不会阻止它。

但是,在一个函数中从URL到图像的唯一方法是使用数据下载来阻止该函数。

答案 1 :(得分:-1)

emit意味着用于信号,而不是插槽。确实,它通常只是一个空的宏,而信号是由您的发射代码调用的实际方法。当插槽属于其他线程时,信号可以直接调用插槽,也可以使用间接异步调用。

您计划的此类插槽无法以异步方式安全地调用。您可以通过自定义信号引用插槽来传递参数,但是如果异步调用,则必须具有同步。其中一种方法是使用未来的课程:QFuturestd::futureQFuture在您的情况下可能更为可取)。这样调用者线程将知道被调用者何时完成下载。只需返回下载状态(错误代码或缺少错误代码)。

您的插槽可能与调用者在同一个线程中实现,但是进程将是一个单独的QThread,它将从插槽运行并更新状态。