如何通过按下和拖动在 Qt Quick/QML 画布中绘制一个矩形
Posted
技术标签:
【中文标题】如何通过按下和拖动在 Qt Quick/QML 画布中绘制一个矩形【英文标题】:How to draw a rectangle in QtQuick/QML canvas by press and draging 【发布时间】:2017-03-27 12:50:02 【问题描述】:我想在图像顶部绘制一些矩形,这些矩形由 QQuickPaintedItem 子类绘制并在 QML 中创建。我使用画布绘制矩形,可以使用鼠标对图像进行平移和缩放。 以下代码不起作用:
Canvas
id:canvas
anchors.fill:parent
// zoom in/out managed by mouse wheel
property double dx:0.0
property double dy:0.0
property double sx:1.0
property double sy:1.0
// mapped mouse position will be displayed on the left top of the window
property double mx:0
property double my:0
// mapped mouse postion when last left buttion pressed
property double lastx:0.0
property double lasty:0.0
// flag
property bool drawing:false
// map x,y to my coordinate
function mapToPaint(x,y)
var mx=(x-dx)/sx;
var my=(y-dy)/sy;
return "x":mx,"y":my;
onPaint:
var ctx = canvas.getContext("2d");
ctx.lineWidth = 1
ctx.strokeStyle = Qt.lighter(root.color)
ctx.clearRect (0, 0, width, height);
ctx.save();
// transform to my coordinate
ctx.translate(dx,dy);
ctx.scale(sx,sy);
// draw a rect
// !! I hope drawing can be displayed when mouse moving,
// !! but the rect wasn't displayed after the mouse button
// !! was released. Instead many rectangles will be showed when
// !! I rolled the mouse wheel after the press-drag operation.
if(drawing)
ctx.rect(lastx,lasty,mx-lastx,my-lasty);
ctx.stroke();
ctx.restore();
MouseArea
id:area
anchors.fill: parent
hoverEnabled:true
preventStealing:true
property double factor: 1.2
onPressed:
if (mouse.button == Qt.LeftButton)
var p=canvas.mapToPaint(mouse.x,mouse.y);
canvas.lastx=p.x;
canvas.lasty=p.y;
canvas.drawing=true
onWheel:
if(wheel.angleDelta.y > 0) // zoom in
var zoomFactor = factor
else // zoom out
zoomFactor = 1/factor
canvas.sx*=zoomFactor;
canvas.sy*=zoomFactor;
canvas.dx=wheel.x-(wheel.x-canvas.dx)*zoomFactor;
canvas.dy=wheel.y-(wheel.y-canvas.dy)*zoomFactor;
canvas.requestPaint();
onPositionChanged:
var p=canvas.mapToPaint(mouse.x,mouse.y);
canvas.mx=p.x;
canvas.my=p.y;
// I hope the rectangle can be showed when draging
// but it didn't work!! why?
// mouse.button == Qt.LeftButton is always false!!!
// so I have to use the canvas.drawing flag
// if (mouse.button == Qt.LeftButton)
if(canvas.drawing)
canvas.requestPaint();
当我按下并拖动鼠标时,我得到了以下图片:
here
更新:
使用 ctx.strokeRect 代替 ctx.rect,我得到了正确的矩形,但在 onPositionChanged 中仍然无法接收到鼠标按钮。
here
【问题讨论】:
【参考方案1】:一般来说,如果您需要实时预览矩形(或任何其他对象),您需要创建一个临时矩形,以便在单击画布时在画布上进行绘制,同时移动鼠标,您只需将该矩形调整为鼠标位置增量的大小,当您松开鼠标时,您实际上在画布上绘制矩形并删除预览。
这就是我要做的,在 QML 中创建一个临时矩形非常简单,所以我想你自己实现它应该没问题?
您当然可以在画布上绘制所有更新,但由于仅删除最后一个更新并不容易,因此我猜使用这种带有临时叠加层的方法会更容易。
【讨论】:
【参考方案2】://handle Painted
Canvas
id:canvas
anchors.fill:parent
// zoom in/out managed by mouse wheel
property double dx:0.0
property double dy:0.0
property double sx:1.0
property double sy:1.0
// mapped mouse position will be displayed on the left top of the window
property double mx:0
property double my:0
// mapped mouse postion when last left buttion pressed
property double lastx:0.0
property double lasty:0.0
// flag
property bool drawing:false
// map x,y to my coordinate
function mapToPaint(x,y)
var mx=(x-dx)/sx;
var my=(y-dy)/sy;
return "x":mx,"y":my;
function clear()
var ctx = canvas.getContext("2d");
ctx.reset();
canvas.requestPaint();
onPaint:
var ctx = canvas.getContext("2d");
ctx.lineWidth = 1
ctx.strokeStyle = 'blue'
ctx.save();
// transform to my coordinate
ctx.translate(dx,dy);
ctx.scale(sx,sy);
// draw a rect
// !! I hope drawing can be displayed when mouse moving,
// !! but the rect wasn't displayed after the mouse button
// !! was released. Instead many rectangles will be showed when
// !! I rolled the mouse wheel after the press-drag operation.
if(drawing)
ctx.rect(lastx,lasty,mx-lastx,my-lasty);
ctx.stroke();
ctx.restore();
MouseArea
id:area
anchors.fill: parent
hoverEnabled:true
preventStealing:true
property double factor: 1.2
onPressed:
var p=canvas.mapToPaint(mouse.x,mouse.y);
canvas.lastx=p.x;
canvas.lasty=p.y;
canvas.drawing=true
onPositionChanged:
canvas.clear();
var p=canvas.mapToPaint(mouse.x,mouse.y);
canvas.mx=p.x;
canvas.my=p.y;
// I hope the rectangle can be showed when draging
// but it didn't work!! why?
// mouse.button == Qt.LeftButton is always false!!!
// so I have to use the canvas.drawing flag
// if (mouse.button == Qt.LeftButton)
if(canvas.drawing)
canvas.requestPaint();
onReleased:
canvas.clear();
console.log(canvas.lastx,canvas.lasty,canvas.mx,canvas.my);
canvas.drawing=false
【讨论】:
您好,请在发布的代码中添加一些说明。以上是关于如何通过按下和拖动在 Qt Quick/QML 画布中绘制一个矩形的主要内容,如果未能解决你的问题,请参考以下文章
如何使 Qt Quick (QML) ListView 项目无法选择?
27.Qt Quick QML-StateTransition