如何只在发出信号时才能使函数返回值?
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的函数。但是,我想确保在返回值之前已下载数据。 (利用下载的()信号?)
答案 0 :(得分:0)
您可能想做的不是返回,而是使用信号发出图像,这样您就可以将其连接到将接收图像并对其执行操作的功能。
在这种情况下,您希望将信号声明为:
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
意味着用于信号,而不是插槽。确实,它通常只是一个空的宏,而信号是由您的发射代码调用的实际方法。当插槽属于其他线程时,信号可以直接调用插槽,也可以使用间接异步调用。
您计划的此类插槽无法以异步方式安全地调用。您可以通过自定义信号引用插槽来传递参数,但是如果异步调用,则必须具有同步。其中一种方法是使用未来的课程:QFuture
或std::future
(QFuture
在您的情况下可能更为可取)。这样调用者线程将知道被调用者何时完成下载。只需返回下载状态(错误代码或缺少错误代码)。
您的插槽可能与调用者在同一个线程中实现,但是进程将是一个单独的QThread,它将从插槽运行并更新状态。