Qml Canvas 实现在图片上画线-图片和直线放大时蓝屏黑屏的解决方法

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();
            }
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇智波盆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值