June 29, 2011

pethor pethor
Lab Rat
1 posts

2D Drawing

 

Hey guys!

I want to make a simple animation: It should only draw a filled circle again and again, moving it from position x:50 y:50 to position x:250 y:250

I want to use the QTimer class for the animation.

In the console I get an error all the time when I try painting:

  1.  QPainter::begin: Paint device returned engine == 0, type: 1
  2. QPainter::setRenderHint: Painter must be active to set rendering hints
  3. QPainter::setPen: Painter not active
  4. QPainter::setBrush: Painter not active

My code looks like this:
SimpleExampleWidget.cpp:

The answer a question beforehand:
The ball class just contains the x, y, and counter information (counter for how often it should be painted)

  1. #include "simpleexamplewidget.h"
  2. #include "ui_simpleexamplewidget.h"
  3. #include <QPaintDevice>
  4. #include <QPaintEvent>
  5. #include <QPainter>
  6. #include <windows.h>
  7. #include <QTimer>
  8. #include <ball.h>
  9.  
  10. Ball b;
  11.  
  12. SimpleExampleWidget::SimpleExampleWidget(QWidget *parent) :
  13.     QWidget(parent),
  14.     ui(new Ui::SimpleExampleWidget)
  15. {
  16.     ui->setupUi(this);
  17. }
  18.  
  19. SimpleExampleWidget::~SimpleExampleWidget()
  20. {
  21.     delete ui;
  22. }
  23.  
  24. void SimpleExampleWidget::updateT(){
  25.     QPainter p(this);
  26.     p.setRenderHint(QPainter::Antialiasing, true);
  27.     p.setPen(QPen(Qt::black, 12, Qt::DashDotLine, Qt::RoundCap));
  28.     p.setBrush(QBrush(Qt::green, Qt::SolidPattern));
  29.     if (b.counter < 10){
  30.         p.drawEllipse(b.x,b.y,400,240);
  31.         b.x+=5;
  32.         b.y+=5;
  33.         b.counter++;
  34.     }
  35. }
  36.  
  37. void SimpleExampleWidget::draw(){
  38.     QTimer *timer = new QTimer;
  39.  
  40.     b.x = 80;
  41.     b.y = 80;
  42.     b.counter = 0;
  43.  
  44.     connect(timer, SIGNAL(timeout()), this, SLOT(updateT()));
  45.     timer->start(50);
  46. }

SimpleExampleWidget.h

  1. #ifndef SIMPLEEXAMPLEWIDGET_H
  2. #define SIMPLEEXAMPLEWIDGET_H
  3.  
  4. #include <QWidget>
  5. #include <QPainter>
  6. #include <QPaintEvent>
  7. #include <QImage>
  8. #include <QImageReader>
  9.  
  10. namespace Ui {
  11.     class SimpleExampleWidget;
  12. }
  13.  
  14. class SimpleExampleWidget : public QWidget
  15. {
  16.     Q_OBJECT
  17.  
  18. public:
  19.     explicit SimpleExampleWidget(QWidget *parent = 0);
  20.     ~SimpleExampleWidget();
  21.     void draw();
  22.     virtual void paintEvent(QPaintEvent *event){
  23.         draw();
  24.     }
  25.  
  26. protected slots:
  27.     void updateT();
  28.  
  29. private:
  30.     Ui::SimpleExampleWidget *ui;
  31. };
  32.  
  33. #endif // SIMPLEEXAMPLEWIDGET_H

Thanks in advance!

Pethor

2 replies

June 29, 2011

sriks sriks
Lab Rat
122 posts

Why would you take the burden of playing the animation and painting. Using QTimer for animation is a pre Qt 4.6 way of doing. You should consider using Animation Framework [doc.qt.nokia.com]. Instead of painting everytime, just paint it once to a pixmap and set it to a QLabel. Using animation framework , animate the “pos” property to the desired end value within the desired timeframe. Also you can use GraphicsView for a simpler way of drawing (see QGraphicsEllipseItem).

Coming to the warning, you are using QPainter wrongly. Qt provides a QPainter with in the paint context or when a paint event is triggered, using which you should draw your widget. So which QPainter are you using in void SimpleExampleWidget::updateT(). That is not the painter which Qt prepared for you so that you can paint on your widget. Atleast try to pass the painter as an argument to the method in which you are painting.

June 29, 2011

Gerolf Gerolf
Robot Herder
3253 posts
srikanthsombhatla wrote:
Coming to the warning, you are using QPainter wrongly. Qt provides a QPainter with in the paint context or when a paint event is triggered, using which you should draw your widget. So which QPainter are you using in void SimpleExampleWidget::updateT(). That is not the painter which Qt prepared for you so that you can paint on your widget. Atleast try to pass the painter as an argument to the method in which you are painting.

This is only partly correct. QPainter is always initialized by the application.

But you should use it inside paintEvent if you draw on the widget. This is, because Qt uses double buffer technologies behind the scenes and manages all this double buffering, invalidation, clipping etc.

so the correct way would be to trigger an update or repaint after updating the position. And inside the paint event, draw whatever you want. Or create a transparent label or custom widget and put the object in there. Then you can move the object by timer or animation framework.

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

 
  ‹‹ Plugging-in Audio File      Memory deallocation problem ››

You must log in to post a reply. Not a member yet? Register here!