Draw a line with QPainter using QGraphicsView subc

2019-04-15 21:01发布

问题:

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.

回答1:

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.