QT 4.5 - как мне получить устройство QPainter в QGraphicsView - PullRequest
15 голосов
/ 13 июля 2009

Я пытаюсь создать программу рисования с QT 4.5, поэтому я использую QGraphicsView для холста и QGraphicsScene для хранения нарисованных элементов. По некоторым причинам я просто не смог получить контекст QPainter в своем собственном производном QGraphicsView

class DrawingCanvas : public QGraphicsView
{ 
  DrawingCanvas::DrawingCanvas(QWidget * parent);

 ...
};

DrawingCanvas::DrawingCanvas(QWidget * parent = 0) : QGraphicsView(parent) 
{
  ....
}

void DrawingCanvas::paintEvent(QPaintEvent& paintEventInfo)
{
  // Result in painter not active
  QPainter(this);
  ...
}

Однако, если я изменю DrawingCanvas на дочерний элемент QWidget, это сработает. Видя, что QGraphicsView является производным от QAbstractScrollArea, затем QFrame, затем QWidget, я ожидаю, что код будет работать.

Итак, я думаю, что вопросы:

1) Почему я не могу использовать paintEvent в QGraphicsView для получения активного QPainter? 2) Возможно ли, что я мог получить один?

Заранее спасибо!

Ответы [ 3 ]

17 голосов
/ 02 февраля 2010

Если кому-то все еще интересно, возможно ли это как-то, ответ - да.

Короткая версия

void DrawingCanvas::paintEvent(QPaintEvent& paintEventInfo)
{
    // Result in painter active
    QPainter(viewport());
    ...
}

Длинная версия

QGraphicsScene не рисует сам по себе, а вместо этого рисует в виджете окна просмотра, который вы ему предоставляете, или по умолчанию QWidget.

Вместо рисования в окне просмотра вы можете получить наложенное рисование, которое будет выровнено по виду, а не по сцене. В качестве альтернативы вы можете использовать QGlWidget и его paintOverlayGl ().

Также не забудьте установить viewportUpdateMode (QGraphicsView :: FullViewportUpdate), иначе вы получите артефакты рендеринга. Возможно, есть более разумный способ избежать артефактов, чем каждый раз обновлять полное представление, но пока я не столкнусь с проблемами производительности, я оставлю его в покое.

4 голосов
/ 13 июля 2009

Правильно, после того, как я немного выдернул волосы, это кажется невозможным, так что вот мое решение. Все, что вы рисуете, должно быть добавлено в QGraphicsScene; так что вы выводите из него свою собственную реализацию.

Самый простой способ - определить временный указатель QGraphicsItem для линий, прямоугольников и т. Д., Которые вы хотите нарисовать.

Переопределить виртуальные события mousePressed (), mouseMove () и mouseRelease () соответственно. В mousePressed () инициализируйте временный указатель QGraphicsItem и добавьте его в сцену.

Внутри mouseMoved (), соответственно установите координаты временного QGraphicsItem. Для mouseReleased создайте копию временного объекта и добавьте его в сцену и удалите временный QGraphicsItem (который вы использовали для рисования линий, прямоугольников и т. Д.) Из сцены.

Полагаю, мораль этого в том, что в QGraphicsView нет контекста QPainter, и вам лучше игнорировать его paintEvent ().

Надеюсь, это поможет кому-то, кто может наткнуться на это.

1 голос
/ 11 октября 2011

Есть еще одна возможность: переопределить drawForeground в представлении. В зависимости от типа элементов, которые нужно нарисовать, это может быть очень простым решением (например, наложение линий маркера) или иногда это больше, чем создание пользовательских элементов в сцене, - зависит от желаемых результатов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...