Qml Canvas 实现在图片上画线-图片和直线放大时蓝屏黑屏的解决方法
背景简介
- 首先,我实现了16位高精度深度相机的.raw格式图片的灰度空间映射和调节,鼠标任意拖拽和以鼠标为中心滚轮任意缩放,以及鼠标在图片上坐标及灰度值的实时显示
- 然后,我使用Canvas填充Image控件并在Image的鼠标域中动态改变所画直线的起始点,终点,并将其传给c++计算直线上的灰度变化图
- 然而,当我们图片放大到一定程度,Canvas画布大小显然也等比例放大,达到一定程度时会出现画面蓝屏或黑屏的情况,鼠标域仍起效,但包括图片和Canvas,画面完全黑屏蓝屏
解决思路
- 设置Canvas尺寸为固定值(绘图区大小),Canvas鼠标域覆盖绘图区,Image鼠标域依旧覆盖Image
- 两组起始点终点分别计算,先计算鼠标在图片上的相对坐标,将这组起始点,终点传给c++计算灰度变化
- Canvas绘图采用另外的逻辑计算坐标,将Image起始点终点相对坐标反映射回绘图区相对坐标,作为Canvas绘直线的起始点,终点。
核心部分源码:
import QtQuick 2.2
import QtQuick.Controls 2.0
import QtGraphicalEffects 1.0
Item {
property double beishu : 1.0;
property int old_x: 0.0;
property int old_y: 0.0;
property double biliX : 1.0;
property double biliY : 1.0;
property bool isPress: false;
property real clickNum;
property real startX;
property real startY;
property real stopX;
property real stopY;
property double startXBili : 1.0;
property double startYBili : 1.0;
property double stopXBili : 1.0;
property double stopYBili : 1.0;
property real tempStartX;
property real tempStartY;
property real tempStopX;
property real tempStopY;
property var ctx;
function resetImageChanged(){
startX = Math.floor(imgView.width * startXBili);
startY = Math.floor(imgView.height * startYBili);
stopX = Math.floor(imgView.width * stopXBili);
stopY = Math.floor(imgView.height * stopYBili);
canvasLineEnd();
canvas.requestPaint();
}
function canvasLineStart(){
tempStartX = imgView.x + imgView.width * startXBili;
tempStartY = imgView.y + imgView.height * startYBili;
tempStopX = tempStartX;
tempStopY = tempStartY;
}
function canvasLineEnd(){
tempStartX = imgView.x + imgView.width * startXBili;
tempStartY = imgView.y + imgView.height * startYBili;
tempStopX = imgView.x + imgView.width * stopXBili;
tempStopY = imgView.y + imgView.height * stopYBili;
}
Item {
id: mapItem
z: 2
clip: true
anchors {
top: parent.top
bottom: parent.bottom
left: parent.right
right: parent.left
}
Image {
id: imgView;
x: mapItem.width/2 - imgView.width/2;
y: mapItem.height/2 - imgView.height/2;
smooth: false;
cache:false;
onXChanged: {
resetImageChanged();
}
onYChanged: {
resetImageChanged();
}
}
Canvas{
id : canvas
anchors.fill: mapItem
visible: righttoolsbar.isChecked == "Line"
onPaint: {
ctx = canvas.getContext("2d");
ctx.lineWidth = 2
ctx.strokeStyle = "#409EFF";
ctx.fillStyle = "#409EFF";
ctx.beginPath()
ctx.clearRect(0,0,canvas.width, canvas.height)
ctx.stroke()
ctx.beginPath()
ctx.moveTo(tempStartX, tempStartY)
ctx.lineTo(tempStopX, tempStopY)
ctx.stroke()
}
}
MouseArea {
id: rawImageMouseArea
anchors.fill: imgView
drag.target: imgView
drag.minimumX: - imgView.width * 0.98
drag.minimumY: - imgView.height * 0.98
drag.maximumX: mapItem.width - imgView.width * 0.02
drag.maximumY: mapItem.height - imgView.height * 0.02
hoverEnabled: true
onClicked: {
if(mouse.button === Qt.LeftButton && righttoolsbar.isChecked == "Line")
{
if(clickNum === 0)
{
startXBili = mouseX / imgView.width;
startYBili = mouseY / imgView.height;
startX = mouseX;
startY = mouseY;
canvasLineStart();
clickNum++;
canvas.requestPaint();
}else {
stopXBili = mouseX / imgView.width;
stopYBili = mouseY / imgView.height;
stopX = mouseX;
stopY = mouseY;
canvasLineEnd();
clickNum = 0;
canvas.requestPaint();
}
}
}
onPositionChanged: {
biliX = mouseX / imgView.width;
biliY = mouseY / imgView.height;
if(righttoolsbar.isChecked == "Line" && clickNum === 1)
{
stopXBili = biliX;
stopYBili = biliY;
stopX = mouseX;
stopY = mouseY;
canvasLineEnd();
canvas.requestPaint();
}
}
onWheel: {
var datla = wheel.angleDelta.y / 120;
old_x = imgView.x + imgView.width * biliX;
old_y = imgView.y + imgView.height * biliY;
if(datla > 0)
{
beishu = beishu / 0.9;
if(beishu > 30) {
beishu = beishu * 0.9;
return;
}
}
else
{
beishu = beishu * 0.9;
if(beishu < 0.2) {
beishu = beishu / 0.9;
return;
}
}
var newH = rawConfig.height * beishu;
var newW = rawConfig.width * beishu;
imgView.height = newH;
imgView.width = newW;
imgView.x = old_x - newW * biliX;
imgView.y = old_y - newH * biliY;
resetImageChanged();
}
}
}
}