QML Canvas - 为啥 requestPaint() 函数不调用绘画?
Posted
技术标签:
【中文标题】QML Canvas - 为啥 requestPaint() 函数不调用绘画?【英文标题】:QML Canvas - Why is the requestPaint() function not calling the paint?QML Canvas - 为什么 requestPaint() 函数不调用绘画? 【发布时间】:2015-04-29 06:45:34 【问题描述】:可重现的例子:
在这里,我使用 QML 画布绘制了一条贝泽曲线。即使我显式更改了开始和结束值从而导致信号生成,绘画也只会被调用一次。
也可以查看输出。 为什么 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!
【问题讨论】:
【参考方案1】: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()
中发出。
【讨论】:
没错。因此,不要像@TheIndependentAquarius 那样实现你的绘画程序。一种方法是缓存您的点(例如使用数组),并且仅在有一定数量的此类点可用时才调用重绘。请求减少,绘画例程可以正确完成。以上是关于QML Canvas - 为啥 requestPaint() 函数不调用绘画?的主要内容,如果未能解决你的问题,请参考以下文章