QTimer::singleShot(0, object SLOT(obj_slot())) 是做什么的?
What does QTimer::singleShot(0, object SLOT(obj_slot())) do?
初学Qt,想了解Qt提供的一个example for download operation. In downloadmanager.cpp,成员函数如下:
void DownloadManager::append(const QUrl &url)
{
if (downloadQueue.isEmpty())
QTimer::singleShot(0, this, SLOT(startNextDownload()));
downloadQueue.enqueue(url);
++totalCount;
}
- 我不明白为什么,如果
downloadQueue
为空,则需要在添加 url 之前激活 startNextDownload()
。 (注意:如果downloadQueue
为空,startNextDownload()
结束程序)
- 我不确定为什么:
QTimer::signleShot(x, y, z)
已经被使用了。据我了解,它是一个计时器,它以 0 毫秒的延迟激活插槽。
- 我无法通过查看 Qt Assistant 弄清楚 singleShot 是一次性设置以在给定的毫秒间隔重复激活插槽还是一次性
澄清:
我是初学者,例如:
statement1;
statement2;
我习惯于看到 statement1
运行 并在继续 statement2
之前完成。但是尝试学习 Qt 并阅读给定的示例,我看到 SLOT(startNextDownload())
在 downloadQueue.enqueue(url);
发生后被激活。我正在尝试了解 为什么 这样做。
当前问题标题的答案
对 QTimer::singleShot(...)
的每次调用都在调用它的线程的 事件循环中执行 **。如果从主线程调用,它将是以 app.exec()
.
开始的事件循环
根据 Qt-Network-Manager-Example,此函数被调用 在 network-manager 被 URL 填充后 single-shot 将在 queue 完全填充后进行处理。很遗憾,qt 文档对这个主题还不是很清楚,所以有关事件处理等的更多信息,请查看 here.
旧问题标题的答案
在我开始之前,计时器用于在额外的线程中进行下载。因此 GUI 保持响应。
完整的downloadNext()
方法是递归的。它只会被调用一次,直到 queue 为空。
看到这个:
void DownloadManager::append(const QStringList &urlList)
{
foreach (QString url, urlList)
append(QUrl::fromEncoded(url.toLocal8Bit())); //Call for only one URL
...
}
void DownloadManager::append(const QUrl &url)
{
if (downloadQueue.isEmpty())
//I'm only called if the queue is empty! And I will be called after the next line. Not instantly!
QTimer::singleShot(0, this, SLOT(startNextDownload()));
downloadQueue.enqueue(url);
++totalCount;
}
在queue为空后每个方法returns至少会打印下载完成的消息。
那么为什么这样做有效?
请参阅下面的第一章。
这会在消息队列中对回调进行排队。
计时器立即结束,一条消息被发布到消息队列中。当进程下次到达主循环时,调用startNextDownload()
函数。此时,URL 在队列中。
startNextDownload()
函数从调度上下文中调用,可以安全地更改 window 内容。这样,DownloadManager
class 可以在多线程应用程序中使用,其中开始下载的线程可能 运行 与 Paint[=24 的处理程序并发=] 事件。通过从处理 Paint 事件的同一线程调用它,您可以确保没有处理此类事件,并且您可以安全地更新小部件。
如果之后需要重新绘制一个小部件,它会请求重新绘制,如果该小部件当前可见,OS 将发送一个 Paint 事件。
您可以先了解有关 Class QTimer 的内容,然后再根据需要获得解决方案,please have a look here for your understanding
初学Qt,想了解Qt提供的一个example for download operation. In downloadmanager.cpp,成员函数如下:
void DownloadManager::append(const QUrl &url)
{
if (downloadQueue.isEmpty())
QTimer::singleShot(0, this, SLOT(startNextDownload()));
downloadQueue.enqueue(url);
++totalCount;
}
- 我不明白为什么,如果
downloadQueue
为空,则需要在添加 url 之前激活startNextDownload()
。 (注意:如果downloadQueue
为空,startNextDownload()
结束程序) - 我不确定为什么:
QTimer::signleShot(x, y, z)
已经被使用了。据我了解,它是一个计时器,它以 0 毫秒的延迟激活插槽。 - 我无法通过查看 Qt Assistant 弄清楚 singleShot 是一次性设置以在给定的毫秒间隔重复激活插槽还是一次性
澄清:
我是初学者,例如:
statement1;
statement2;
我习惯于看到 statement1
运行 并在继续 statement2
之前完成。但是尝试学习 Qt 并阅读给定的示例,我看到 SLOT(startNextDownload())
在 downloadQueue.enqueue(url);
发生后被激活。我正在尝试了解 为什么 这样做。
当前问题标题的答案
对 QTimer::singleShot(...)
的每次调用都在调用它的线程的 事件循环中执行 **。如果从主线程调用,它将是以 app.exec()
.
根据 Qt-Network-Manager-Example,此函数被调用 在 network-manager 被 URL 填充后 single-shot 将在 queue 完全填充后进行处理。很遗憾,qt 文档对这个主题还不是很清楚,所以有关事件处理等的更多信息,请查看 here.
旧问题标题的答案
在我开始之前,计时器用于在额外的线程中进行下载。因此 GUI 保持响应。
完整的downloadNext()
方法是递归的。它只会被调用一次,直到 queue 为空。
看到这个:
void DownloadManager::append(const QStringList &urlList)
{
foreach (QString url, urlList)
append(QUrl::fromEncoded(url.toLocal8Bit())); //Call for only one URL
...
}
void DownloadManager::append(const QUrl &url)
{
if (downloadQueue.isEmpty())
//I'm only called if the queue is empty! And I will be called after the next line. Not instantly!
QTimer::singleShot(0, this, SLOT(startNextDownload()));
downloadQueue.enqueue(url);
++totalCount;
}
在queue为空后每个方法returns至少会打印下载完成的消息。
那么为什么这样做有效? 请参阅下面的第一章。
这会在消息队列中对回调进行排队。
计时器立即结束,一条消息被发布到消息队列中。当进程下次到达主循环时,调用startNextDownload()
函数。此时,URL 在队列中。
startNextDownload()
函数从调度上下文中调用,可以安全地更改 window 内容。这样,DownloadManager
class 可以在多线程应用程序中使用,其中开始下载的线程可能 运行 与 Paint[=24 的处理程序并发=] 事件。通过从处理 Paint 事件的同一线程调用它,您可以确保没有处理此类事件,并且您可以安全地更新小部件。
如果之后需要重新绘制一个小部件,它会请求重新绘制,如果该小部件当前可见,OS 将发送一个 Paint 事件。
您可以先了解有关 Class QTimer 的内容,然后再根据需要获得解决方案,please have a look here for your understanding