15

我正在尝试使用 QT 4.5 做一个绘画程序,所以我使用 QGraphicsView 作为画布,并使用 QGraphicsScene 来存储绘制的项目。由于某些原因,我无法在我自己的派生 QGraphicsView 中获得 QPainter 上下文

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) 为什么我不能在 QGraphicsView 中使用 paintEvent 来获得活动的 QPainter?2)有可能我可以得到一个吗?

提前致谢!

4

3 回答 3

17

如果有人仍然想知道这是否可能,答案是肯定的。

精简版

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

长版

QGraphicsScene 不会对自己进行绘画,而是在您提供给它的视口小部件或默认情况下为 QWidget 上绘画。

相反,通过在视口上绘画,您可以实现与视图而非场景对齐的叠加绘画。或者,您可以使用 QGlWidget 及其paintOverlayGl()。

还记得设置 viewportUpdateMode(QGraphicsView::FullViewportUpdate) 否则你会得到渲染工件。可能有比每次都更新整个视图更聪明的方法来避免工件,但在遇到性能问题之前,我会让它休息。

于 2010-02-02T07:48:47.980 回答
4

对了,拔了一会儿头发后,这似乎是不可能的,所以这是我的解决方案。您绘制的所有内容都必须添加到 QGraphicsScene;所以你从中派生出你自己的实现。

最简单的方法是为要绘制的线条、矩形等定义一个临时的 QGraphicsItem 指针。

相应地覆盖虚拟 mousePressed()、mouseMove() 和 mouseRelease() 事件。在 mousePressed() 上,初始化临时 QGraphicsItem 指针并将其添加到场景中。

在 mouseMoved() 中,相应地设置临时 QGraphicsItem 的坐标。对于 mouseReleased,创建临时对象的副本并将其添加到场景中,然后从场景中移除临时 QGraphicsItem(您一直在使用它来绘制线条、矩形等)。

我想这样做的寓意是在 QGraphicsView 中没有 QPainter 上下文,最好忽略它的paintEvent()。

希望这对可能偶然发现此问题的人有所帮助。

于 2009-07-13T09:36:21.527 回答
1

还有另一种可能性:在视图上覆盖drawForeground。根据您需要绘制的项目类型,这可能是一个非常简单的解决方案(例如,标记线的叠加),或者有时它比在场景中创建自定义项目更多工作 - 取决于您想要的结果。

于 2011-10-11T10:12:02.677 回答