Всем привет!
Вопрос к знатокам и любителям)
Задача - создание графического элемента(ГЭ) в виде прямоугольника, который бы при вращении на
произвольный угол методом rotate класса QGraphicsView сохранял ориентацию в виджете-просмоторщике унаследованном от QGraphicsView.
Т.е. схема примерно следующая: создаю сцену, в ней размещаю этот самый графический элемент (горизонтально:длинной стороной вдоль нижней части экрана). Затем создаю виджет просмоторщик, у которого есть методы для масштабирования и поворота сцены на 5 градусов (QGraphicsView::rotate(5)). Вызов методов вешаю на кнопки . Назначаю этому просмоторщику ранее созданную сцену. Далее, жму кнопку масштабирования - ГЭ масштабируется, жму кнопку поворота, сцена поворачивается, вместе с ней ГЭ, но при этом он сохраняет свою горизонтальную ориентацию.
Такой ГЭ на базе QGraphicsRectItem и QObject сделать-таки удалось, работает исправно, но я уверен, что есть более элегантные решения. Реализовал примерно так:
1. В классе ГЭ есть слот для поворота вокруг центра прямоугольника на заданный угол
2. При нажатии кнопки поворота просмоторщика высылается сигнал для ГЭ со значением угла поворота (5)
3. Соответствующий слот ГЭ делает поворот на -5 градусов
Может быть не нужен огород со слотами и сигналами, а в QGraphicsItem есть метод, который бы вызывался каждый раз при QGraphicsView::rotate и при этом в таком методе можно было бы получить значение угла поворота из вида.
Или имеет смысл вообще свой итем замутить?
Спасибо
=====================================================================================================
вот такое решение получилось
class MyItem : public QAbstractGraphicsShapeItem {
public:
MyItem(QGraphicsItem *parent = 0);
~MyItem();
virtual QRectF boundingRect() const;
virtual void paint(QPainter* ppainter, const QStyleOptionGraphicsItem*, QWidget*);
private:
QLineF line_prev;
qreal angle;
};
// реализация
//--------------------------------------------------------------------------------
MyItem::MyItem(QGraphicsItem *parent) : QAbstractGraphicsShapeItem(parent) {
angle = 0;
}
//--------------------------------------------------------------------------------
void MyItem::paint(QPainter* ppainter, const QStyleOptionGraphicsItem*, QWidget*) {
ppainter->save();
QTransform trans = ppainter->transform();
QLineF line_cur = trans.map(QLineF(QPointF(0,0), QPointF(10,0)));
qreal curAngle = line_prev.angleTo(line_cur);
if(fabs(curAngle-360) < 1e-8 || fabs(curAngle) < 1e-8)
{
qDebug() << "ZOOM";
ppainter->setTransform(trans.rotate(angle));
}
else
{
qDebug() << "ROTATE";
angle = fmod(angle + curAngle, 360);
ppainter->setTransform(trans.rotate(angle));
}
line_prev = line_cur;
ppainter->setPen(QPen(Qt::green, 1));
ppainter->drawLine(0,0,50,0);
ppainter->setPen(QPen(Qt::red, 1));
ppainter->drawLine(0,0,0,50);
ppainter->restore();
}
и не большой коммент.
Для прорисовки итема используется метод paint. У него на входе есть указатель на объект класса рисовальщика QPainter.
По этому указателю можно получить матрицу текущего преобразования (ppainter->transform()
. С помощию неё можно получить точки в СК виджета-просмоторщика. Пусть линия имеет координаты (10,0) в СК итема. Переводим её в СК просмоторщика и сохраняем в line_prev. При очередном попадании в paint() переводим линию с координатами (10,0) в СК просмоторщика и сохраняем её в line_cur. Потом считаем угол между 2 линиями line_prev и line_cur(т.е. угол между линией до поворота и после). Далее используем полученный угол для "выравнивания" итема.