2

Question: I can't make the GraphicsView's paintEvent be called or in other words I don't know how to make QPainter work altogether.

  • I'm using qtcreator's designer to place a QGraphicsView into the main window.
  • I sub-classed QGraphicsView (class Draw) overriding the paintEvent and hold an instance of this subclass (Draw draw) in the main window (I wanted to move the complicated drawing elsewhere)
  • I created a new QGraphicsScene and assign it to both QGraphicsView's (ui->graphicsView and draw) so when I draw inside the Draw it would visibly take effect in the
    ui->graphicsview as well (I hope).
  • I'm sure when I draw using the new scene object, I get a visible result (however, I don't want to use the scene object for drawing but the QPainter. The reason why is for another question so I hope it's not essential) Therefore I'm trying to subclass the QGraphicsView and override the paintEvent so I get the QPainter p(this) easily.
  • When an event occurs I call MyRepaint() in Window.cpp where I'm trying to invoke paintEvent() on my Draw object - but it's not working.

Main 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"; 
}

subclassing QGraphicsView, file: 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);
}

Output:

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

Maybe I've chosen a completely wrong approach.

Daniel Katz
  • 2,271
  • 3
  • 25
  • 27

2 Answers2

3

QGraphicsView is designed to work with QGraphicsScene. If you just want to draw lines, then derive from QWidget and override it's paintEvent. In designer promote QWidget to your derived class.

Also, Qt has a good documentation. I advice you to visit this page.

K117
  • 118
  • 1
  • 7
  • yes I googled that page, its a needlessly too long article. I need a minimal example and tutorial how to do it. Now I'm looking at the "promotion thing" that you mentioned, I didn't know about it. – Daniel Katz Jun 23 '16 at 03:15
  • https://bitbucket.org/K117/qtlineexample/src Simplest line example i could write. – K117 Jun 23 '16 at 03:29
  • Promotion. In Designer click RMB on widget and select "Promote to...", enter name of your derived class. You can promote widget to your class derived from it. – K117 Jun 23 '16 at 03:34
  • QPainter is relatively low-level tool, you have to make it white yourself. `painter.fillRect(rect(), Qt::white);` before any other drawing. – K117 Jun 23 '16 at 03:49
0

For short, You can use QGraphicsLineItem *QGraphicsScene::addLine(...)

This is the Graphics View Framwork way to draw a line, while the accepted answer is the QWidget way

QGraphicsView is a part of the Grapics View Framework. Usually by calling update(), a widget is able to trigger paintEvent(). However, as far as i know,in the Graphics View Framework, it's impossible for QGraphicsView to tigger the paintEvent() by calling update()

There's one more things, you should know, according to qt documents:

Warning: When the paintdevice is a widget, QPainter can only be used inside a paintEvent() function or in a function called by paintEvent()

Jim Green
  • 531
  • 4
  • 6