QML Canvas - 为什么 requestPaint() 函数不调用绘画?
QML Canvas - Why is the requestPaint() function not calling the paint?
可重现的例子:
这里我用QML画了一条beizer曲线canvas。即使我显式更改开始值和结束值从而导致信号生成,绘制也只被调用一次。
也请查看输出。 为什么requestPaint()函数不调用paint?
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!
requestPaint()
only requests that the Canvas
is repainted. If you take a look into 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()
.
中发出
可重现的例子:
这里我用QML画了一条beizer曲线canvas。即使我显式更改开始值和结束值从而导致信号生成,绘制也只被调用一次。
也请查看输出。 为什么requestPaint()函数不调用paint?
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!
requestPaint()
only requests that the Canvas
is repainted. If you take a look into 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()
.