使用 QGraphicsView 子类用 QPainter 画一条线
Draw a line with QPainter using QGraphicsView subclass
问题:
我无法让 GraphicsView 的 paintEvent 被调用,或者换句话说,我不知道如何让 QPainter 一起工作。
- 我正在使用 qtcreator 的设计器将 QGraphicsView 放入主 window。
- 我将 QGraphicsView (
class Draw
) 子类化,覆盖 paintEvent
并在主 window 中保存这个子类 (Draw draw
) 的一个实例(我想把复杂的图移到别处)
- 我创建了一个
new QGraphicsScene
并将其分配给 QGraphicsView's
(ui->graphicsView
和 draw
)所以当我在 Draw
内部绘制时它会明显在
ui->graphicsview
也生效(我希望)。
- 我确定当我使用新的
scene
对象进行绘图时,我得到了一个可见的结果(但是,我不想使用 scene
对象进行绘图但是 QPainter
。原因是为了另一个问题,所以我希望它不是必需的)因此我试图子类化 QGraphicsView
并覆盖 paintEvent 所以我很容易得到 QPainter p(this)
。
- 当事件发生时,我在
Window.cpp
中调用 MyRepaint()
,我试图在我的 Draw
对象上调用 paintEvent()
- 但它不起作用。
主要window'Window.cpp':
Window::Window(QWidget* parent) :
QMainWindow(parent),
ui(new Ui::Window),
draw(*this) //my own QGraphicsView instance (see class below)
{
ui->setupUi(this);
//assigning a new scene to draw and to window's graphicsView
this->scene = new QGraphicsScene(this);
this->draw.setScene(scene);
this->ui->graphicsView->setScene(scene);
}
void Window::MyRepaint()
{
qInfo() << "Repaint - start" << this->draw.scene();
this->draw.scene()->update(this->draw.sceneRect());
this->draw.repaint();
this->draw.viewport()->update();
/*only the following line made the paintEvent executed eventually but without a visible result and with an error in the output*/
this->draw.paintEvent(NULL);
qInfo() << "Repaint - end";
}
子类化 QGraphicsView,文件:Draw.h:
class Window;
class Draw : public QGraphicsView{
private:
Window& parent;
public:
Draw(Window &parent);
void paintEvent(QPaintEvent*e) override;
};
Draw.cpp
void Draw::paintEvent(QPaintEvent *e)
{
qInfo() << "trying to draw";
QPainter p(this);
p.setPen(QPen(Qt::black, 12, Qt::DashDotLine, Qt::RoundCap));
p.drawLine(0, 0, 200, 200);
}
输出:
Repaint - start QGraphicsScene(0x15c7eca8)
trying to draw
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::setPen: Painter not active
QPainter::viewport: Painter not active
QPainter::end: Painter not active, aborted
Repaint - end
也许我选择了一个完全错误的方法。
QGraphicsView 旨在与 QGraphicsScene 一起使用。如果你只想画线,那么从 QWidget 派生并覆盖它的 paintEvent。在设计器中将 QWidget 提升到您的派生 class.
另外,Qt 有很好的文档。我建议您访问 this 页面。
简而言之,您可以使用 QGraphicsLineItem *QGraphicsScene::addLine(...)
这是Graphics View Framwork画线的方式,而接受的答案是QWidget方式
QGraphicsView 是图形视图框架的一部分。通常通过调用 update(),小部件能够触发 paintEvent()。然而,据我所知,在图形视图框架中,QGraphicsView 不可能通过调用 update()
来触发 paintEvent()
根据qt文档,还有一件事你应该知道:
Warning: When the paintdevice is a widget, QPainter can only be used inside a paintEvent() function or in a function called by paintEvent()
问题: 我无法让 GraphicsView 的 paintEvent 被调用,或者换句话说,我不知道如何让 QPainter 一起工作。
- 我正在使用 qtcreator 的设计器将 QGraphicsView 放入主 window。
- 我将 QGraphicsView (
class Draw
) 子类化,覆盖paintEvent
并在主 window 中保存这个子类 (Draw draw
) 的一个实例(我想把复杂的图移到别处) - 我创建了一个
new QGraphicsScene
并将其分配给QGraphicsView's
(ui->graphicsView
和draw
)所以当我在Draw
内部绘制时它会明显在ui->graphicsview
也生效(我希望)。 - 我确定当我使用新的
scene
对象进行绘图时,我得到了一个可见的结果(但是,我不想使用scene
对象进行绘图但是QPainter
。原因是为了另一个问题,所以我希望它不是必需的)因此我试图子类化QGraphicsView
并覆盖 paintEvent 所以我很容易得到QPainter p(this)
。 - 当事件发生时,我在
Window.cpp
中调用MyRepaint()
,我试图在我的Draw
对象上调用paintEvent()
- 但它不起作用。
主要window'Window.cpp':
Window::Window(QWidget* parent) :
QMainWindow(parent),
ui(new Ui::Window),
draw(*this) //my own QGraphicsView instance (see class below)
{
ui->setupUi(this);
//assigning a new scene to draw and to window's graphicsView
this->scene = new QGraphicsScene(this);
this->draw.setScene(scene);
this->ui->graphicsView->setScene(scene);
}
void Window::MyRepaint()
{
qInfo() << "Repaint - start" << this->draw.scene();
this->draw.scene()->update(this->draw.sceneRect());
this->draw.repaint();
this->draw.viewport()->update();
/*only the following line made the paintEvent executed eventually but without a visible result and with an error in the output*/
this->draw.paintEvent(NULL);
qInfo() << "Repaint - end";
}
子类化 QGraphicsView,文件:Draw.h:
class Window;
class Draw : public QGraphicsView{
private:
Window& parent;
public:
Draw(Window &parent);
void paintEvent(QPaintEvent*e) override;
};
Draw.cpp
void Draw::paintEvent(QPaintEvent *e)
{
qInfo() << "trying to draw";
QPainter p(this);
p.setPen(QPen(Qt::black, 12, Qt::DashDotLine, Qt::RoundCap));
p.drawLine(0, 0, 200, 200);
}
输出:
Repaint - start QGraphicsScene(0x15c7eca8)
trying to draw
QWidget::paintEngine: Should no longer be called
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::setPen: Painter not active
QPainter::viewport: Painter not active
QPainter::end: Painter not active, aborted
Repaint - end
也许我选择了一个完全错误的方法。
QGraphicsView 旨在与 QGraphicsScene 一起使用。如果你只想画线,那么从 QWidget 派生并覆盖它的 paintEvent。在设计器中将 QWidget 提升到您的派生 class.
另外,Qt 有很好的文档。我建议您访问 this 页面。
简而言之,您可以使用 QGraphicsLineItem *QGraphicsScene::addLine(...)
这是Graphics View Framwork画线的方式,而接受的答案是QWidget方式
QGraphicsView 是图形视图框架的一部分。通常通过调用 update(),小部件能够触发 paintEvent()。然而,据我所知,在图形视图框架中,QGraphicsView 不可能通过调用 update()
来触发 paintEvent()根据qt文档,还有一件事你应该知道:
Warning: When the paintdevice is a widget, QPainter can only be used inside a paintEvent() function or in a function called by paintEvent()