QT 4.5 - как я могу получить QPainter-устройство в QGraphicsView
Я пытаюсь сделать программу рисования с 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) Возможно ли, что я мог бы получить один?
Спасибо заранее!
Ответы
Ответ 1
Если кто-то все еще задается вопросом, возможно ли это как-то, ответ да.
Краткая версия
void DrawingCanvas::paintEvent(QPaintEvent& paintEventInfo)
{
// Result in painter active
QPainter(viewport());
...
}
Длинная версия
QGraphicsScene не рисует сама по себе, а вместо этого рисует виджет виджета, который вы ему даете, или по умолчанию QWidget.
Покраска на видовом экране вместо этого вы можете достичь наложенной живописи, которая будет выровнена по отношению к виду, а не к сцене. В качестве альтернативы вы можете использовать QGlWidget и его paintOverlayGl().
Также не забудьте установить viewportUpdateMode (QGraphicsView:: FullViewportUpdate), или вы получите рендеринг артефактов. Возможно, более умный способ избежать артефактов, чем обновлять весь просмотр каждый раз, но пока я не столкнусь с проблемами производительности, я оставлю это.
Ответ 2
Правильно, после вытягивания моих волос какое-то время это кажется невозможным, так что вот мое решение. Все, что вы рисуете, должно быть добавлено в QGraphicsScene; поэтому вы получаете от него свою собственную реализацию.
Самый простой способ - определить временный указатель QGraphicsItem для строк, прямоугольников и т.д., которые вы хотите рисовать.
Переопределите событие virtual mousePressed(), mouseMove() и mouseRelease() соответственно. На mousePressed() инициализируйте указатель temp QGraphicsItem и добавьте его в сцену.
Внутри mouseMoved() задайте координаты temp QGraphicsItem соответственно. Для mouseReleased создайте копию временного объекта и добавьте его в сцену и удалите из сцены темный QGraphicsItem (который вы использовали для рисования линий, прямоугольников и т.д.).
Я предполагаю, что мораль этого заключается в том, что в QGraphicsView нет контекста QPainter, и вам лучше игнорировать его paintEvent().
Надеюсь, это поможет кому-то, кто может наткнуться на это.
Ответ 3
Есть и другая возможность: переопределить drawForeground в представлении. В зависимости от вида предметов, которые нужно рисовать, это может быть очень простое решение (например, наложение линий маркеров), а иногда и больше, чем создание пользовательских элементов в сцене - зависит от ваших желаемых результатов.