Invoke Canvas onPaint exactly once per update?
<p><em>AKA: Canvas requestPaint() too slow; requestAnimationFrame() too fast</em></p>

<p>I'm trying to create a QML Canvas that repaints as fast as possible—once per update in the main UI render loop—in order to create an FPS timer.</p>

<p>I initially wrote this simple test:</p>

<pre class="lang-qml prettyprint-override"><code>import QtQuick 2.7
import QtQuick.Window 2.2

Window {
    visible:true; width:100; height:100
    Canvas {
        anchors.fill:parent
        onPaint: console.log(+new Date)
    }
}
</code></pre>

<p>I only get the callback once. So I added <a href="http://doc.qt.io/qt-5/qml-qtquick-canvas.html#requestPaint-method" rel="nofollow"><code>requestPaint()</code></a>:</p>

<pre class="lang-qml prettyprint-override"><code>onPaint: {
    console.log(+new Date)
    requestPaint()
}
</code></pre>

<p>No change: I still only get one callback. Same if I use <code>markDirty()</code>. Same if I actually paint something on the canvas each callback.</p>

<p>So I moved to <a href="http://doc.qt.io/qt-5/qml-qtquick-canvas.html#requestAnimationFrame-method" rel="nofollow"><code>requestAnimationFrame()</code></a>:</p>

<pre class="lang-qml prettyprint-override"><code>import QtQuick 2.7
import QtQuick.Window 2.2
Window {
    visible:true; width:100; height:100
    Canvas {
        anchors.fill:parent
        Component.onCompleted: crank()
        function crank(){
            console.log(+new Date)
            requestAnimationFrame(crank)
        }
    }
}
</code></pre>

<p>Now I get callbacks, but way too many. On average, I get 77 callbacks per millisecond, some times as many as 127 callbacks in a single millisecond. So many callbacks that nothing else in the application displays, not even initially. Even if I remove the <code>console.log()</code>, to prove that I'm not i/o bound).</p>

<p>How can I get my canvas to repaint once "per frame", so that I can measure the FPS semi-accurately? Any why does <code>requestPaint()</code> not actually work? And why is <code>requestAnimationFrame()</code> apparently useless?</p>