2
votes

I want to draw a grid (series of lines) when I click the draw button, and I want them to clear when I click the clear button.

I got the grid to appear as a standalone program, but I cannot figure out how to combine it with QPushButton.

I get the following message when clicking on the Draw button while the program is running.

"QPainter::begin: Paint device returned engine == 0, type: 1 QPainter::setPen: Painter not active"

Thank you

#include <QtGui> 
#include <QPainter>
#include "myqtapp.h"

// including <QtGui> saves us to include every class user, <QString>, <QFileDialog>,...

myQtApp::myQtApp(QWidget *parent)
{
    setupUi(this); // this sets up GUI

        // signals/slots mechanism in action
        connect( pushButton_draw, SIGNAL( clicked() ), this, SLOT( draw() ) );
    connect( pushButton_clear, SIGNAL( clicked() ), this, SLOT( clear() ) ); 
    connect( pushButton_about, SIGNAL( clicked() ), this, SLOT( about() ) ); 
}



void myQtApp::draw()
{
    //draw the grid

    int lineSpacing(30),// line spacing in pixels
            numberOfLines;

    QPen pen(Qt::black, 2, Qt::SolidLine);

    QPainter painter(this);
    painter.setPen(pen);

    //Grid takes up at most a 400x400 area starting at (right 150, down 50) from upper left
    numberOfLines = 400/lineSpacing; //Round down grid size to fit in 400x400
    for(int i = 0; i<numberOfLines; i++){
        painter.drawLine(150, 50+i*lineSpacing, 150+(numberOfLines-1)*lineSpacing, 50+i*lineSpacing);
        painter.drawLine(150+i*lineSpacing, 50, 150+i*lineSpacing, 50+(numberOfLines-1)*lineSpacing );
    }

}
1

1 Answers

4
votes

The problem you are having is because you are trying to draw on the UI using QPainter outside of the paintEvent() call of a widget - from the Qt docs :

The common use of QPainter is inside a widget's paint event: Construct and customize (e.g. set the pen or the brush) the painter. Then draw. Remember to destroy the QPainter object after drawing.

If you try and draw on the widget outside of the paintEvent() call, results are unpredictable.

The correct way to do this would be something like this:

   // myQtApp.h
   class myQtApp : public QWidget
   {
   Q_OBJECT
   public:
      myQtApp(QWidget *parent = 0); // Constructor as you have
   protected:
      void paintEvent(QPaintEvent *event); // This is re-implemented from QWidget
   protected slots:
      void draw();
   private:
      bool drawTheLines;
   }

and

   // myQtApp.cpp
   void myQtApp::paintEvent(QPaintEvent *event)
   {
      QPainter painter(this);

      if(drawTheLines)
      {
         // Do the drawing here - as in your current draw() function
      }

      QWidget::paintEvent(event); // call the base class so everything else is drawn OK
   }


   void draw();
   {
      drawTheLines = true;
      update(); // This forces a repaint of the widget with paintEvent()
   }