import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 ApplicationWindow { width: 640 height: 480 visible: true title: qsTr("Paint") ScrollView { anchors.fill: parent // Показывать полосы прокрутки. ScrollBar.horizontal.policy: ScrollBar.AlwaysOn ScrollBar.vertical.policy: ScrollBar.AlwaysOn // Обрезать содержимое по размеру окна прокрутки. clip: true Canvas { id: picture implicitWidth: 1920 implicitHeight: 1080 // Рисование прямой линии? property bool drawLine: true // Параметры линии. property var lineColor: Qt.rgba(1, 0, 0, 1) property var lineWidth: 5 // Координаты сегмента. property real lastX: 0 property real lastY: 0 property real curX: 0 property real curY: 0 // Изображение до начала рисования линии. property var imageData: null onPaint: { var ctx = getContext("2d") if (drawLine && !imageData) { // Начало рисования линии. Запоминаем текущее изображение. imageData = ctx.getImageData(0, 0, width, height) } else if (drawLine) { // Восстанавливаем изображение для удаления линии. ctx.clearRect(0, 0, width, height) ctx.drawImage(imageData, 0, 0) } // Устанавливаем параметры рисования. ctx.lineCap = "round" ctx.strokeStyle = lineColor ctx.lineWidth = lineWidth // Рисуем сегмент. // XXX: Для ломанной лучше было бы не начинать новый // путь для каждого сегмента, а запоминать и рисовать // весь путь целиком. Это решение плохо работает для // полупрозрачного цвета. ctx.beginPath() ctx.moveTo(lastX, lastY) ctx.lineTo(curX, curY) ctx.stroke() if (!drawLine) { // Начало следующего сегмента. lastX = curX lastY = curY } } MouseArea { anchors.fill: parent preventStealing: true onPressed: { picture.imageData = null // Запоминаем координаты начала сегмента. picture.curX = picture.lastX = mouseX picture.curY = picture.lastY = mouseY // Запрос на перерисовку холста. picture.requestPaint() } onPositionChanged: { // Обновление координат при перемещении курсора. picture.curX = mouseX picture.curY = mouseY picture.requestPaint() } } } } }