В QtQuick практически отсутствуют элементы, представляющие собой геометрические фигуры (есть только Rectangle). Видимо, предполагается, что если требуется рисовать что-то хоть сколько-то сложное, нужно использовать элемент Canvas. Однако, в случае интерактивного интерфейса Canvas не очень удобен - чтобы обработать, например, нажатие клавиши мышки по элементу на Canvas, нужно получить координаты указателя мыши, понять, какой элемент расположен по этим координатам, понять, какие еще элементы затрагиваются этим событием, и перестроить Canvas. В случае, если интерфейс построен из отдельных элементов (типа Item или Rectangle), каждый элемент может сам обрабатывать свои события, а связывать элементы между собой можно через сигналы-слоты. Получается гораздо удобнее.
Итак, я не хочу использовать Canvas, но мне необходимо нарисовать линию. Так как у нас есть только Rectangle, то будем использовать именно его: ведь линия - это тот же прямоугольник, просто с очень маленькой высотой (например, один пиксель), повернутый на определенный угол.
Представленный ниже код QML я позаимствовал отсюда.
Видно, что линия задается через координаты двух точек - начала и конца линии. Причем координаты начала совпадают с координатами элемента Rectangle. Центром вращения назначается левый верхний угол, итоговая ширина элемента Rectangle и угол поворота рассчитываются исходя из координат начала и конца линии.
Итак, я не хочу использовать Canvas, но мне необходимо нарисовать линию. Так как у нас есть только Rectangle, то будем использовать именно его: ведь линия - это тот же прямоугольник, просто с очень маленькой высотой (например, один пиксель), повернутый на определенный угол.
Представленный ниже код QML я позаимствовал отсюда.
import QtQuick 2.0 Rectangle { id: l property real x1: 0 property real y1: 0 property real x2: 0 property real y2: 0 color: "black" height: 1 smooth: true; x: x1 y: y1 - height / 2 transformOrigin: Item.Left; width: getWidth(x1, y1, x2, y2); rotation: getSlope(x1, y1, x2, y2); function getWidth(sx1, sy1, sx2, sy2) { var w = Math.sqrt(Math.pow((sx2 - sx1), 2) + Math.pow((sy2 - sy1), 2)); return w; } function getSlope(sx1,sy1,sx2,sy2) { var a, m, d; var b = sx2 - sx1; if (b === 0) { x = x + height return 90; } a = sy2 - sy1; m = a / b; d = Math.atan(m) * 180 / Math.PI; if (a < 0 && b < 0) return d + 180; else if (a >= 0 && b >= 0) return d; else if (a < 0 && b >= 0) return d; else if (a >= 0 && b < 0) return d + 180; else return 0; } }
Видно, что линия задается через координаты двух точек - начала и конца линии. Причем координаты начала совпадают с координатами элемента Rectangle. Центром вращения назначается левый верхний угол, итоговая ширина элемента Rectangle и угол поворота рассчитываются исходя из координат начала и конца линии.
У вас ошибка. Вы нарушаете принцип единственной ответственности изменяя свойство x из привязки свойства rotation. Это приводит к Binding loop warning и к другим неприятным моментам. Так же return 90 - не учитывает направления вдоль оси OY.
ОтветитьУдалитьif (b === 0) {
x = x + height
return 90;
}
Замените на:
if (b === 0)
return Math.sign(sy2 - sy1) * 90