Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qquickframeanimation.cpp
Go to the documentation of this file.
1
// Copyright (C) 2022 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant reason:default
4
5
#
include
"qquickframeanimation_p.h"
6
7
#
include
<
QtCore
/
qcoreapplication
.
h
>
8
#
include
<
QtCore
/
qelapsedtimer
.
h
>
9
#
include
"private/qabstractanimationjob_p.h"
10
#
include
<
private
/
qobject_p
.
h
>
11
#
include
<
qdebug
.
h
>
12
13
QT_BEGIN_NAMESPACE
14
15
class
QFrameAnimationJob
:
public
QAbstractAnimationJob
16
{
17
int
duration
()
const
override
{
18
return
1;
19
}
20
};
21
22
class
QQuickFrameAnimationPrivate
:
public
QObjectPrivate
,
public
QAnimationJobChangeListener
23
{
24
Q_DECLARE_PUBLIC(QQuickFrameAnimation)
25
public
:
26
QQuickFrameAnimationPrivate
() {}
27
28
void
animationCurrentLoopChanged
(
QAbstractAnimationJob
*)
override
{
29
maybeTick
();
30
}
31
32
void
maybeTick
()
33
{
34
Q_Q
(
QQuickFrameAnimation
);
35
if
(!
running
||
paused
)
36
return
;
37
38
qint64
elapsedTimeNs
=
elapsedTimer
.
nsecsElapsed
();
39
qint64
frameTimeNs
=
elapsedTimeNs
-
prevElapsedTimeNs
;
40
if
(
prevFrameTimeNs
!=
frameTimeNs
) {
41
frameTime
=
qreal
(
frameTimeNs
) / 1000000000.0;
42
Q_EMIT
q
->
frameTimeChanged
();
43
}
44
45
const
qreal
f
= 0.1;
46
qreal
newSmoothFrameTime
=
f
*
frameTime
+ (1.0 -
f
) *
smoothFrameTime
;
47
if
(!
qFuzzyCompare
(
newSmoothFrameTime
,
smoothFrameTime
)) {
48
smoothFrameTime
=
newSmoothFrameTime
;
49
Q_EMIT
q
->
smoothFrameTimeChanged
();
50
}
51
52
q
->
setElapsedTime
(
elapsedTime
+
frameTime
);
53
54
const
int
frame
= (
firstTick
&&
currentFrame
> 0) ? 0 :
currentFrame
+ 1;
55
q
->
setCurrentFrame
(
frame
);
56
57
prevElapsedTimeNs
=
elapsedTimeNs
;
58
prevFrameTimeNs
=
frameTimeNs
;
59
firstTick
=
false
;
60
61
Q_EMIT
q
->
triggered
();
62
}
63
64
// Handle the running/pausing state updates.
65
void
updateState
()
66
{
67
if
(!
componentComplete
)
68
return
;
69
70
if
(
running
&& !
paused
) {
71
if
(
firstTick
) {
72
elapsedTime
= 0;
73
elapsedTimer
.
start
();
74
}
75
prevElapsedTimeNs
=
elapsedTimer
.
nsecsElapsed
();
76
frameJob
.
start
();
77
}
else
{
78
frameJob
.
stop
();
79
}
80
}
81
82
private
:
83
QFrameAnimationJob
frameJob
;
84
QElapsedTimer elapsedTimer;
85
int
currentFrame = 0;
86
qreal frameTime = 0.0;
87
qreal smoothFrameTime = 0.0;
88
qreal elapsedTime = 0.0;
89
qint64 prevFrameTimeNs = 0;
90
qint64 prevElapsedTimeNs = 0;
91
bool
running =
false
;
92
bool
paused =
false
;
93
bool
componentComplete =
false
;
94
bool
firstTick =
true
;
95
};
96
97
/*!
98
\qmltype FrameAnimation
99
\nativetype QQuickFrameAnimation
100
\inqmlmodule QtQuick
101
\ingroup qtquick-interceptors
102
\since 6.4
103
\brief Triggers a handler at every animation frame update.
104
105
A FrameAnimation can be used to trigger an action every time animations
106
have progressed and an animation frame has been rendered. See the documentation
107
about the \l{qtquick-visualcanvas-scenegraph.html}{Scene Graph} for in-depth
108
information about the threaded and basic render loops.
109
110
For general animations, prefer using \c NumberAnimation and other \c Animation
111
elements as those provide declarative way to describe the animations.
112
113
FrameAnimation on the other hand should be used for custom imperative animations
114
and in use-cases like these:
115
\list
116
\li When you need to run some code on every frame update. Or e.g. every other frame,
117
maybe using progressive rendering.
118
\li When the speed / target is changing during the animation, normal QML animations
119
can be too limiting.
120
\li When more accurate frame update time is needed, e.g. for fps counter.
121
\endlist
122
123
Compared to \c Timer which allows to set the \c interval time, FrameAnimation runs
124
always in synchronization with the animation updates. If you have used \c Timer
125
with a short interval for custom animations like below, please consider switching
126
to use FrameAnimation instead for smoother animations.
127
\code
128
// BAD
129
Timer {
130
interval: 16
131
repeat: true
132
running: true
133
onTriggered: {
134
// Animate something
135
}
136
}
137
138
// GOOD
139
FrameAnimation {
140
running: true
141
onTriggered: {
142
// Animate something
143
}
144
}
145
\endcode
146
*/
147
QQuickFrameAnimation::QQuickFrameAnimation(QObject *parent)
148
: QObject(*(
new
QQuickFrameAnimationPrivate), parent)
149
{
150
Q_D(QQuickFrameAnimation);
151
d->frameJob.addAnimationChangeListener(d, QAbstractAnimationJob::CurrentLoop);
152
d->frameJob.setLoopCount(-1);
153
}
154
155
/*!
156
\qmlsignal QtQuick::FrameAnimation::triggered()
157
158
This signal is emitted when the FrameAnimation has progressed to a new frame.
159
*/
160
161
/*!
162
\qmlproperty bool QtQuick::FrameAnimation::running
163
164
If set to true, starts the frame animation; otherwise stops it.
165
166
\a running defaults to false.
167
168
\sa stop(), start(), restart()
169
*/
170
bool
QQuickFrameAnimation::isRunning()
const
171
{
172
Q_D(
const
QQuickFrameAnimation);
173
return
d->running;
174
}
175
176
void
QQuickFrameAnimation::setRunning(
bool
running)
177
{
178
Q_D(QQuickFrameAnimation);
179
if
(d->running != running) {
180
d->running = running;
181
d->firstTick =
true
;
182
Q_EMIT runningChanged();
183
d->updateState();
184
}
185
}
186
187
/*!
188
\qmlproperty bool QtQuick::FrameAnimation::paused
189
190
If set to true, pauses the frame animation; otherwise resumes it.
191
192
\a paused defaults to false.
193
194
\sa pause(), resume()
195
*/
196
bool
QQuickFrameAnimation::isPaused()
const
197
{
198
Q_D(
const
QQuickFrameAnimation);
199
return
d->paused;
200
}
201
202
void
QQuickFrameAnimation::setPaused(
bool
paused)
203
{
204
Q_D(QQuickFrameAnimation);
205
if
(d->paused != paused) {
206
d->paused = paused;
207
Q_EMIT pausedChanged();
208
d->updateState();
209
}
210
}
211
212
/*!
213
\qmlproperty int QtQuick::FrameAnimation::currentFrame
214
\readonly
215
216
This property holds the number of frame updates since the start.
217
When the frame animation is restarted, currentFrame starts from \c 0.
218
219
The following example shows how to react on frame updates.
220
221
\code
222
FrameAnimation {
223
running: true
224
onTriggered: {
225
// Run code on every frame update.
226
}
227
}
228
\endcode
229
230
This property can also be used for rendering only every nth frame. Consider an
231
advanced usage where the UI contains two heavy elements and to reach smooth 60fps
232
overall frame rate, you decide to render these heavy elements at 30fps, first one
233
on every even frames and second one on every odd frames:
234
235
\code
236
FrameAnimation {
237
running: true
238
onTriggered: {
239
if (currentFrame % 2 == 0)
240
updateUIElement1();
241
else
242
updateUIElement2();
243
}
244
}
245
\endcode
246
247
By default, \c frame is 0.
248
*/
249
int
QQuickFrameAnimation::currentFrame()
const
250
{
251
Q_D(
const
QQuickFrameAnimation);
252
return
d->currentFrame;
253
}
254
255
/*!
256
\qmlproperty real QtQuick::FrameAnimation::frameTime
257
\readonly
258
259
This property holds the time (in seconds) since the previous frame update.
260
261
The following example shows how to use frameTime to animate item with
262
varying speed, adjusting to screen refresh rates and possible fps drops.
263
264
\code
265
Rectangle {
266
id: rect
267
property real speed: 90
268
width: 100
269
height: 100
270
color: "red"
271
anchors.centerIn: parent
272
}
273
274
FrameAnimation {
275
id: frameAnimation
276
running: true
277
onTriggered: {
278
// Rotate the item speed-degrees / second.
279
rect.rotation += rect.speed * frameTime
280
}
281
}
282
\endcode
283
284
By default, \c frameTime is 0.
285
*/
286
qreal QQuickFrameAnimation::frameTime()
const
287
{
288
Q_D(
const
QQuickFrameAnimation);
289
return
d->frameTime;
290
}
291
292
/*!
293
\qmlproperty real QtQuick::FrameAnimation::smoothFrameTime
294
\readonly
295
296
This property holds the smoothed time (in seconds) since the previous frame update.
297
298
The following example shows how to use smoothFrameTime to show average fps.
299
300
\code
301
Text {
302
text: "fps: " + frameAnimation.fps.toFixed(0)
303
}
304
305
FrameAnimation {
306
id: frameAnimation
307
property real fps: smoothFrameTime > 0 ? (1.0 / smoothFrameTime) : 0
308
running: true
309
}
310
\endcode
311
312
By default, \c smoothFrameTime is 0.
313
*/
314
qreal QQuickFrameAnimation::smoothFrameTime()
const
315
{
316
Q_D(
const
QQuickFrameAnimation);
317
return
d->smoothFrameTime;
318
}
319
320
/*!
321
\qmlproperty real QtQuick::FrameAnimation::elapsedTime
322
\readonly
323
324
This property holds the time (in seconds) since the previous start.
325
326
By default, \c elapsedTime is 0.
327
*/
328
qreal QQuickFrameAnimation::elapsedTime()
const
329
{
330
Q_D(
const
QQuickFrameAnimation);
331
return
d->elapsedTime;
332
}
333
334
/*!
335
\qmlmethod void QtQuick::FrameAnimation::start()
336
\brief Starts the frame animation.
337
338
If the frame animation is already running, calling this method has no effect. The
339
\c running property will be true following a call to \c start().
340
*/
341
void
QQuickFrameAnimation::start()
342
{
343
setRunning(
true
);
344
}
345
346
/*!
347
\qmlmethod void QtQuick::FrameAnimation::stop()
348
\brief Stops the frame animation.
349
350
If the frame animation is not running, calling this method has no effect. Both the \c running and
351
\c paused properties will be false following a call to \c stop().
352
*/
353
void
QQuickFrameAnimation::stop()
354
{
355
setRunning(
false
);
356
setPaused(
false
);
357
}
358
359
/*!
360
\qmlmethod void QtQuick::FrameAnimation::restart()
361
\brief Restarts the frame animation.
362
363
If the FrameAnimation is not running it will be started, otherwise it will be
364
stopped, reset to initial state and started. The \c running property
365
will be true following a call to \c restart().
366
*/
367
void
QQuickFrameAnimation::restart()
368
{
369
stop();
370
start();
371
}
372
373
/*!
374
\qmlmethod void QtQuick::FrameAnimation::pause()
375
\brief Pauses the frame animation.
376
377
If the frame animation is already paused or not \c running, calling this method has no effect.
378
The \c paused property will be true following a call to \c pause().
379
*/
380
void
QQuickFrameAnimation::pause()
381
{
382
setPaused(
true
);
383
}
384
385
/*!
386
\qmlmethod void QtQuick::FrameAnimation::resume()
387
\brief Resumes a paused frame animation.
388
389
If the frame animation is not paused or not \c running, calling this method has no effect.
390
The \c paused property will be false following a call to \c resume().
391
*/
392
void
QQuickFrameAnimation::resume()
393
{
394
setPaused(
false
);
395
}
396
397
/*!
398
\qmlmethod void QtQuick::FrameAnimation::reset()
399
\brief Resets the frame animation properties.
400
401
Calling this method resets the \c frame and \c elapsedTime to their initial
402
values (0). This method has no effect on \c running or \c paused properties
403
and can be called while they are true or false.
404
405
The difference between calling \c reset() and \c restart() is that \c reset()
406
will always initialize the properties while \c restart() initializes them only
407
at the next frame update which doesn't happen e.g. if \c restart() is
408
immediately followed by \c pause().
409
*/
410
void
QQuickFrameAnimation::reset()
411
{
412
Q_D(QQuickFrameAnimation);
413
setElapsedTime(0);
414
setCurrentFrame(0);
415
d->prevElapsedTimeNs = 0;
416
d->elapsedTimer.start();
417
}
418
419
/*!
420
\internal
421
*/
422
void
QQuickFrameAnimation::classBegin()
423
{
424
Q_D(QQuickFrameAnimation);
425
d->componentComplete =
false
;
426
}
427
428
/*!
429
\internal
430
*/
431
void
QQuickFrameAnimation::componentComplete()
432
{
433
Q_D(QQuickFrameAnimation);
434
d->componentComplete =
true
;
435
d->updateState();
436
}
437
438
/*!
439
\internal
440
*/
441
void
QQuickFrameAnimation::setCurrentFrame(
int
frame)
442
{
443
Q_D(QQuickFrameAnimation);
444
if
(d->currentFrame != frame) {
445
d->currentFrame = frame;
446
Q_EMIT currentFrameChanged();
447
}
448
}
449
450
/*!
451
\internal
452
*/
453
void
QQuickFrameAnimation::setElapsedTime(qreal elapsedTime)
454
{
455
Q_D(QQuickFrameAnimation);
456
if
(!qFuzzyCompare(d->elapsedTime, elapsedTime)) {
457
d->elapsedTime = elapsedTime;
458
Q_EMIT elapsedTimeChanged();
459
}
460
}
461
462
QT_END_NAMESPACE
463
464
#
include
"moc_qquickframeanimation_p.cpp"
QFrameAnimationJob
Definition
qquickframeanimation.cpp:16
QFrameAnimationJob::duration
int duration() const override
Definition
qquickframeanimation.cpp:17
QQuickFrameAnimationPrivate
Definition
qquickframeanimation.cpp:23
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qtdeclarative
src
quick
util
qquickframeanimation.cpp
Generated on
for Qt by
1.18.0