import QtQuick import QtQuick.Controls import AntiClipSettings Item { id: root property int dargWidth: 12 property color openDoorAreaColor: "green" property var openDoorAreaPoints: [] property bool openDoorAreaEnabled: false property var shieldedAreaPoints: [] property bool shieldedAreaEnabled: false property color antiClipAreaColor: "blue" property var antiClipAreaPoints: [] property bool antiClipAreaEnabled: false property var defaultShieldedAreaPoints: [Qt.point(6, 6), Qt.point(40, 60), Qt.point(598, 6), Qt.point(633, 60)] Item { anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top anchors.bottom: controlBar.top Image { id: image anchors.centerIn: parent cache: false fillMode: Image.PreserveAspectFit source: "image://videoframe/" property real aspectRatio: 16 / 9 width: Math.min(parent.width, parent.height * aspectRatio) height: width / aspectRatio Canvas { id: canvas anchors.fill: parent onPaint: { var ctx = canvas.getContext("2d") ctx.clearRect(0, 0, canvas.width, canvas.height) if (openDoorAreaEnabled &&(openDoorAreaPoints.length > 0)) { ctx.strokeStyle = openDoorAreaColor ctx.lineWidth = 2 ctx.beginPath() let point = scaledPoint(openDoorAreaPoints[0], width, height) ctx.moveTo(point.x, point.y) for (var i = 1; i < openDoorAreaPoints.length; i++) { point = scaledPoint(openDoorAreaPoints[i], width, height) ctx.lineTo(point.x, point.y) } ctx.closePath() ctx.stroke() } if (antiClipAreaEnabled && (antiClipAreaPoints.length > 0)) { ctx.strokeStyle = antiClipAreaColor ctx.lineWidth = 2 ctx.beginPath() let point = scaledPoint(antiClipAreaPoints[0], width, height) ctx.moveTo(point.x, point.y) for (var i = 1; i < antiClipAreaPoints.length; i++) { point = scaledPoint(antiClipAreaPoints[i], width, height) ctx.lineTo(point.x, point.y) } ctx.closePath() ctx.stroke() } if (shieldedAreaEnabled &&(shieldedAreaPoints.length > 0)) { ctx.strokeStyle = "green" let point0 = scaledPoint(shieldedAreaPoints[0], width, height) let point1 = scaledPoint(shieldedAreaPoints[1], width, height) let point2 = scaledPoint(shieldedAreaPoints[2], width, height) let point3 = scaledPoint(shieldedAreaPoints[3], width, height) ctx.strokeRect(point0.x, point0.y, point1.x - point0.x, point1.y - point0.y) ctx.strokeRect(point2.x, point2.y, point3.x - point2.x, point3.y - point2.y) } } } Repeater { id: repeater visible: openDoorAreaEnabled model: openDoorAreaPoints delegate: Rectangle { width: dargWidth height: dargWidth visible: openDoorAreaEnabled color: openDoorAreaColor x: scaledPoint(modelData, canvas.width, canvas.height).x - width / 2 y: scaledPoint(modelData, canvas.width, canvas.height).y - height / 2 } } Repeater { id: shieldedAreaRepeater model: shieldedAreaPoints visible: shieldedAreaEnabled delegate: Rectangle { width: dargWidth height: dargWidth visible: shieldedAreaEnabled color: "green" x: scaledPoint(modelData, canvas.width, canvas.height).x - width / 2 y: scaledPoint(modelData, canvas.width, canvas.height).y - height / 2 } } Repeater { id: antiAreaRepeater visible: antiClipAreaEnabled model: antiClipAreaPoints delegate: Rectangle { visible: antiClipAreaEnabled width: dargWidth height: dargWidth color: antiClipAreaColor x: scaledPoint(modelData, canvas.width, canvas.height).x - width / 2 y: scaledPoint(modelData, canvas.width, canvas.height).y - height / 2 } } MouseArea { anchors.fill: parent property int draggedOpenDoorAreaPointIndex: -1 property int draggedShieldedAreaPointIndex: -1 property int draggedAntiAreaPointIndex: -1 onPressed: mouse => { if(openDoorAreaEnabled){ for (var i = 0; i < openDoorAreaPoints.length; i++) { let point = scaledPoint( openDoorAreaPoints[i], canvas.width, canvas.height) if (isInside(mouse.x, mouse.y, point)) { draggedOpenDoorAreaPointIndex = i break } } } if (draggedOpenDoorAreaPointIndex >= 0) return if(shieldedAreaEnabled){ for (let i = 0; i < shieldedAreaPoints.length; i++) { let point = scaledPoint( shieldedAreaPoints[i], canvas.width, canvas.height) if (isInside(mouse.x, mouse.y, point)) { draggedShieldedAreaPointIndex = i break } } } if (draggedShieldedAreaPointIndex >= 0) return if(antiClipAreaEnabled){ for (let i = 0; i < antiClipAreaPoints.length; i++) { let point = scaledPoint( antiClipAreaPoints[i], canvas.width, canvas.height) if (isInside(mouse.x, mouse.y, point)) { draggedAntiAreaPointIndex = i break } } } } onReleased: { if (draggedOpenDoorAreaPointIndex >= 0) { App.updateOpenDoorAreaPoints(openDoorAreaPoints) draggedOpenDoorAreaPointIndex = -1 } if (draggedShieldedAreaPointIndex >= 0) { App.updateShieldedAreaPoints(shieldedAreaPoints) draggedShieldedAreaPointIndex = -1 } if (draggedAntiAreaPointIndex >= 0) { App.updateAntiClipAreaPoints(antiClipAreaPoints) draggedAntiAreaPointIndex = -1 } } onPositionChanged: mouse => { if ((mouse.x < 0) || (mouse.x > canvas.width) || (mouse.y < 0) || (mouse.y > canvas.height)) return if (draggedOpenDoorAreaPointIndex >= 0) { openDoorAreaPoints[draggedOpenDoorAreaPointIndex] = standardPoint(Qt.point(mouse.x, mouse.y), canvas.width, canvas.height) canvas.requestPaint() repeater.model = openDoorAreaPoints } else if (draggedShieldedAreaPointIndex >= 0) { shieldedAreaPoints[draggedShieldedAreaPointIndex] = standardPoint(Qt.point(mouse.x, mouse.y), canvas.width, canvas.height) canvas.requestPaint() shieldedAreaRepeater.model = shieldedAreaPoints } else if (draggedAntiAreaPointIndex >= 0) { antiClipAreaPoints[draggedAntiAreaPointIndex] = standardPoint(Qt.point(mouse.x, mouse.y), canvas.width, canvas.height) canvas.requestPaint() antiAreaRepeater.model = antiClipAreaPoints } } function isInside(x, y, point) { let edge = dargWidth / 2 return x >= point.x - edge && x <= point.x + edge && y >= point.y - edge && y <= point.y + edge } } } } Row { id: controlBar anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom Switch { text: "开门区域" checked: openDoorAreaEnabled onToggled: App.currentOpenDoorAreaEnabled = checked } Switch { text: "防夹区域" checked: antiClipAreaEnabled onToggled: App.currentAntiClipAreaEnabled = checked } Switch { text: "屏蔽区域" checked: shieldedAreaEnabled onToggled: App.currentShieldedAreaEnabled = checked } } // 转换为显示画点 function scaledPoint(point, width, height) { let x = point.x * width / 640 let y = point.y * height / 360 return Qt.point(x, y) } // 转换为设备画点(640x360) function standardPoint(point, width, height) { let x = point.x * 640 / width let y = point.y * 360 / height return Qt.point(x, y) } Connections { target: App function onNewVideoFrame() { image.source = "" image.source = "image://videoframe/" } function onCurrentOpenDoorAreaPointsChanged() { canvas.requestPaint() } function onCurrentShieldedAreaPointsChanged() { canvas.requestPaint() } function onCurrentAntiClipAreaPointsChanged() { canvas.requestPaint() } function onCurrentOpenDoorAreaEnabledChanged(){ canvas.requestPaint() } function onCurrentShieldedAreaEnabledChanged(){ canvas.requestPaint() } function onCurrentAntiClipAreaEnabledChanged(){ canvas.requestPaint() } } }