Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: vintik от Март 25, 2011, 00:41



Название: QGraphicsItem который бы не менял угол поворота при вызове QGraphicsView::rotate
Отправлено: vintik от Март 25, 2011, 00:41
Всем привет!
Вопрос к знатокам и любителям)
Задача - создание графического элемента(ГЭ) в виде прямоугольника, который бы при вращении на произвольный угол методом 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(т.е. угол между линией до поворота и после). Далее используем полученный угол для "выравнивания" итема.


Название: Re: QGraphicsItem который бы не менял угол поворота при вызове QGraphicsView::rotate
Отправлено: Swa от Март 25, 2011, 16:01
Попробуйте QGraphicsItem::setFlags(QGraphicsItem::ItemIgnoresTransformations)


Название: Re: QGraphicsItem который бы не менял угол поворота при вызове QGraphicsView::rotate
Отправлено: vintik от Март 25, 2011, 21:40
Попробуйте QGraphicsItem::setFlags(QGraphicsItem::ItemIgnoresTransformations)
Смотрел в сторону этого флага. Про него так написано:
Элемент игнорирует наследуемые преобразования (т.е. его позиция всё ещё связана с его родителем, но поворот, масштабирование или обрезание родителя или вида игнорируются). Этот флаг полезен для сохранения текстовой метки горизонтальной и немасштабированной, поэтому она будет читаема если вид преобразован. Если этот флаг установлен, геометрия вида элемента и сцены обрабатываются раздельно.

Т.е. масштабированию он не подвергается, а хотелось бы чтобы он масштабировался как и сцена(или родитель)