В 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