QT singleShot设置循环
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QT singleShot设置循环相关的知识,希望对你有一定的参考价值。
void QRfbClient::eventOperation()
...........
QTimer::singleShot(10, this, SLOT(eventOperation()));
上面一段代码的意思是不是产生一个眉0.01秒执行一次的循环呢
但是在这里,你把槽函数设置成eventOperation(),那么当定时器到达时候,就会执行这个函数,在这个函数中定时器又会再次发出信号,然后执行槽函数eventOperation,这样循环往复的
所以这是一个每隔10毫秒就执行一次的循环
不知理解没有 参考技术A 首先上面的计时器只会执行一次,如果想要每隔0.01秒触发的话可以用
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(eventOperation()));
timer->start(10);
这段代码如果设置setSingleShot(true)的话,程序也将只执行一次。
QTimer::singleShot(0, object SLOT(obj_slot())) 做啥?
【中文标题】QTimer::singleShot(0, object SLOT(obj_slot())) 做啥?【英文标题】:What does QTimer::singleShot(0, object SLOT(obj_slot())) do?QTimer::singleShot(0, object SLOT(obj_slot())) 做什么? 【发布时间】:2017-01-07 17:20:17 【问题描述】:我是初学者学习Qt,并试图了解Qt提供的example进行下载操作。在downloadmanager.cpp 中,成员函数如下:
void DownloadManager::append(const QUrl &url)
if (downloadQueue.isEmpty())
QTimer::singleShot(0, this, SLOT(startNextDownload()));
downloadQueue.enqueue(url);
++totalCount;
我很困惑,为什么如果downloadQueue
为空,则需要在添加网址之前激活startNextDownload()
。 (注意:如果downloadQueue
为空,则startNextDownload()
结束程序)
我不确定为什么:QTimer::signleShot(x, y, z)
已经被使用了。据我了解,它是一个以 0 毫秒的延迟激活插槽的计时器。
通过查看 Qt 助手,我无法确定 singleShot 是一次性设置,以在给定的毫秒间隔内重复激活插槽,还是一次性设置
澄清:
我是初学者,例如:
statement1;
statement2;
我习惯于看到statement1
运行和完成,然后再继续处理statement2
。但是尝试学习 Qt 并阅读给定的示例,我看到 SLOT(startNextDownload())
在 downloadQueue.enqueue(url);
发生之后被激活。我正在尝试了解为什么这样做。
【问题讨论】:
是 QT4 吗?你不是在用 QT5 吗? 我使用的是 Qt 4.8.7。 好吧,只是想知道你是 qt 的初学者。通常初学者会使用我认为的最新版本:) 感谢这个问题,讽刺的是它帮助我更好地理解了这些东西 【参考方案1】:这会在消息队列中排队回调。
计时器立即过去,一条消息被发送到消息队列。当进程下一次到达主循环时,将调用startNextDownload()
函数。此时,该 URL 已在队列中。
startNextDownload()
函数是从调度上下文中调用的,在这里可以安全地更改窗口内容。这样,DownloadManager
类可以在多线程应用程序中使用,其中启动下载的线程可能与 Paint 事件的处理程序同时运行。通过从处理 Paint 事件的同一线程调用它,您可以确定没有此类事件正在处理,并且您可以安全地更新小部件。
如果之后需要重新绘制小部件,则它会要求重新绘制,如果小部件当前可见,操作系统将发送 Paint 事件。
【讨论】:
谢谢,这有点清楚了。由于我没有进行任何线程编程,因此我将其理解为将其推送到待办事项队列中,稍后将一一完成。但是为什么 SLOT(startNextDownload() 确保在将 url 添加到 downloadQueue 之后运行(即使插槽出现/推送到添加之前要做的事情)?我也不明白:什么是主循环,是什么导致进程到达主循环?但我不知道“当进程下一次到达主循环时”是什么意思:主循环是什么,是什么导致它到达主循环? @RobertC.Holland,等等.. 你是对的,在多线程应用程序中,这可能会很糟糕。我会将其重写为bool const needToStart = downloadQueue.isEmpty(); downloadQueue.enqueue(url); if(needToStart) QTimer::singleShot(...);
。
@RobertC.Holland,主循环是程序空闲时所在的位置。这是一个无限循环,它从队列中获取第一个事件并处理它,如果没有事件剩余,它会要求操作系统给其他进程 CPU 时间或关闭 CPU,直到发生有趣的事情。 GUI程序通常只包含一堆事件处理程序,当它们返回时,程序返回到主循环。
感谢您的解释。我现在这样解释程序(如果我错了,请纠正我):QTimer::singleShot(0, this, SLOT(startNextDownload()));
告诉在 0 毫秒内添加/推送到主循环的消息队列。所以,消息队列上的最后一件事是运行成员函数DownloadManager::append()
(其中singleShot 不会跳转到调用槽,而只是调度运行之后)等等,接下来的事情将是DownloadManager::startNextDownload()
after DownloadManager::append()
完全结束。谢谢!
计时器是个谎言。 “计时器立即过去”的说法是错误的。 QTimer::singleShot(0, ...)
用词不当,它所做的事情与 QTimer::singleShot
的所有其他调用完全不同。这是一个特例,意思是:“下次事件循环启动时再做”。时间无处可寻,而且 Qt 甚至使用名为“定时器”的句柄在内部实现它的事实具有误导性:那些“定时器”实际上并不使用任何平台定时器,它们只是事件循环使用的句柄。一个零持续时间的计时器在 Qt 中并不是一个计时器,尽管它的名字如此。【参考方案2】:
对当前问题标题的回答
对QTimer::singleShot(...)
的每次调用都在调用它的线程的事件循环中执行 **。如果从主线程调用,它将是以app.exec()
开始的事件循环。
根据 Qt-Network-Manager-Example,这个函数在网络管理器被 URL 填充之后调用, 所以在队列被完全填充后,单次将被处理.不幸的是,qt 文档对此主题还不是很清楚,因此有关事件处理等的更多信息,请查看here。
旧问题标题的答案
在我开始之前,计时器用于在额外线程中进行下载。所以 GUI 保持响应。
完整的downloadNext()
方法是递归的。它只会被调用一次,直到队列为空。
看到这个:
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;
队列为空后,每个方法都会返回,并且至少会打印下载完成的消息。
那么为什么会这样呢? 请参阅下面的第一章。
【讨论】:
感谢您提供详细信息,但是QTimer::singleShot(0, this, SLOT(startNextDownload()));
作为一个单独的线程,它如何保证在downloadQueue.enqueue(url);
发生之前运行(假设它只有一个主线程)?
因为它运行在qt事件线程上,调用app.exec()
后开始执行
我不确定这是否正确。 AFAIK 插槽将在 this 所属的任何线程上运行。这不一定是主 UI 线程(根据文档,该函数将在接收器的线程中运行)。因此,正如目前所说,答案是完全错误的。
您能否参考一下文档。
@ArthurP.R.:请参阅此blog.bbv.ch/2012/10/03/multithreaded-programming-with-qt 博客文章,了解当前在 Qt 中实现的线程关联性的解释。小故事 - 每个 QObject 都有线程亲和性,排队的信号连接会自动在正确的线程中保持执行【参考方案3】:
在你最终得到你想要的解决方案之前,你可以了解关于 Class QTimer 的事情,please have a look here for your understanding
【讨论】:
很抱歉,这并没有正确解决问题。以上是关于QT singleShot设置循环的主要内容,如果未能解决你的问题,请参考以下文章
QT延时方法整理(QTimer::singleShot,QWaitCondition,QDateTime.secsTo三种新方法)
Qt中使用定时器(可使用QObject::timerEvent定时执行,QTimer::singleShot可只触发一次)
QTimer::singleShot(0, object SLOT(obj_slot())) 做啥?