QTimer 不重置 remainingTime 的 setInterval

7

我有一个用QT编写的应用程序,使用了QTimer。它基本上是一个游戏,所有的动作都由计时器控制。游戏包括增加\减少游戏速度的能力。增加速度的代码如下:

    timerValue -= speedUpValue;
    if (timerValue < maxSpeed) {
        timerValue = maxSpeed;
    }
    timer -> setInterval(timerValue); 

speedUpValuemaxSpeed是常量。减速的代码几乎与加速的代码相同。问题在于setInterval会重置内部计时器,因此如果您不断地快速增加或减少速度,游戏最终永远无法进行,因为remainingTime不断被重置。有没有办法手动设置remainingTime或更改间隔而不重置它?


1
不,没有办法在计时器自动重新启动的情况下更改时间间隔。但是,当计时器超时时仅更新时间间隔可能可以实现类似的效果。 - RA.
1个回答

4
您可以完全忽略定时器对象,而改为使用静态方法QTimer::singleShot(...),并在每个计时器事件上使用timerValue设置新的单次触发。因此,无论timerValue被修改的频率如何,每个计时器周期都将以旧值完成,并以当前值进行调度。
正如RA所提到的,您也可以通过将setInterval()移到计时器事件中有效地实现相同的功能,基本上与上述相同,但保留了计时器对象(如果您由于某种原因需要它)。
正如Craig在评论中提到的那样,第一种方法还将确保不会累积计时器事件,在您的游戏逻辑需要更长时间的情况下。此外,如果您采用异步设计,可能会在连续运行计时器的情况下在旧的游戏周期完成之前开始执行下一个游戏周期。
因此,最好不要使用连续运行的计时器,而是手动安排每个下一个游戏周期,仅在需要时进行安排。例如,如果游戏结束,则可能不需要安排另一个游戏周期。此外,这将允许更精细地控制游戏速度的准确性,在游戏周期执行完成后,您可以计算出直到下一个周期所需的剩余时间,并以该值进行安排,或者如果执行时间过长,则可以立即安排。

1
每次使用单次触发的另一个优点是事件不会累积。如果您使用QTimer并且无法像生成它们一样快地消耗其信号,则它们会积累。单次触发不会像这样累积,因为您只有在处理当前触发时才会启动下一个触发。主要缺点是间隔的准确性/规律性较低。 - Craig Scott
@CraigScott:我知道这些都是老新闻,但这是我目前能找到的最好的信息。这个答案似乎表明周期性QTimer事件不会累积。更像是在事件循环结束时检查是否已经过了规定的时间。如果是,即使粗略地,它也会触发一个事件并重置计时器。哪一个是正确的? - AaronD
@AaronD 自从我发表上述评论以来已经过了很长时间,但我认为它是基于我所见到的实际行为而非假设的。对于我来说,这已经是太久以前的事情了,以至于我无法记住细节,因此您需要进行自己的测试以验证最新Qt的行为。 - Craig Scott
还要考虑连接到计时器信号的插槽可能是一个排队连接,因此累积可能不是在计时器本身中进行,而是在延迟插槽调用的队列中进行。 - Craig Scott

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接