QML Canvas - 为什么requestPaint()函数没有调用paint?

时间:2015-04-29 06:45:35

标签: javascript qt canvas qml qtquick2

可重复示例:

这里我用QML画布绘制了一个beizer曲线。即使我明确地更改了开始值和结束值,因此只会调用一次paint,从而导致信号生成。

也可以看到输出。 为什么requestPaint()函数不会调用绘图?

Test.qml

import QtQuick 2.4

Canvas
{
    id: head; width: parent.width; height: parent.height

    property int    curveStartX: -1
    property int    curveStartY: -1
    property int    curveEndX: -1
    property int    curveEndY: -1

    Rectangle
    {
        id: startControlPoint
        x:  head.curveStartX; y: head.curveStartY; width: 15; height: 15; color: "red"; radius: 100

        onXChanged:  
        { 
           console.log("start called x1"); 
           head.requestPaint(); 
           console.log("start called x2")
        }

        onYChanged:  
        { 
           console.log("start called y1"); 
           head.requestPaint(); 
           console.log("start called y2")
        }
    }

    Rectangle
    {
        id: endControlPoint
        x: head.curveEndX; y: head.curveEndY; width: 15; height: 15; color: "red"; radius: 100
        onXChanged:  head.requestPaint ()
        onYChanged:  head.requestPaint ()
    }

    onPaint:
    {
        console.log ("Paint got called!")

        var ctx = getContext ("2d");
        ctx.beginPath ();
        ctx.clearRect (0, 0, head.height, head.width);
        ctx.fill ();

        ctx.strokeStyle = head.curveColor
        ctx.lineWidth   = 2;

        ctx.beginPath ();
        // start point of the curve.
        ctx.moveTo (head.curveStartX, head.curveStartY)
        ctx.bezierCurveTo (startControlPoint.x, startControlPoint.y,
                           endControlPoint.x, endControlPoint.y,
                           head.curveEndX, head.curveEndY);
        ctx.stroke ();
    }
}

main.qml

import QtQuick 2.4
import QtQuick.Window 2.2

Window
{
    visible: true
    height: 500
    width: 500

    Test
    {
        id: what
    }

    Component.onCompleted:
    {
        what.curveStartX = 0
        what.curveStartY = 0

        what.curveEndX = 50
        what.curveEndY = 50
        /////////////////////////////////////////
        what.curveStartX = 10
        what.curveStartY = 10

        what.curveEndX = 60
        what.curveEndY = 60
    }
}

输出:

QML debugging is enabled. Only use this in a safe environment.
qml: start called x1
qml: start called x2
qml: start called y1
qml: start called y2
qml: start called x1
qml: start called x2
qml: start called y1
qml: start called y2
qml: start called x1
qml: start called x2
qml: start called y1
qml: start called y2
qml: Paint got called!

1 个答案:

答案 0 :(得分:3)

requestPaint()请求 Canvas被重新绘制。如果您查看QQuickCanvasItem::requestPaint()

void QQuickCanvasItem::requestPaint()
{
    markDirty(d_func()->canvasWindow);
}

您可以看到它调用QQuickCanvasItem::markDirty()

void QQuickCanvasItem::markDirty(const QRectF& rect)
{
    Q_D(QQuickCanvasItem);
    if (!d->available)
        return;

    d->dirtyRect |= rect;

    polish();
}

反过来调用QQuickItem::polish()

void QQuickItem::polish()
{
    Q_D(QQuickItem);
    if (!d->polishScheduled) {
        d->polishScheduled = true;
        if (d->window) {
            QQuickWindowPrivate *p = QQuickWindowPrivate::get(d->window);
            bool maybeupdate = p->itemsToPolish.isEmpty();
            p->itemsToPolish.insert(this);
            if (maybeupdate) d->window->maybeUpdate();
        }
    }
}

因此,只要场景图决定它就绪,就会发出paint()信号。信号以QQuickCanvasItem::updatePolish()发出。