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:

    bq. @ QPainter::begin: Paint device returned engine == 0, type: 1
    QPainter::setRenderHint: Painter must be active to set rendering hints
    QPainter::setPen: Painter not active
    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)

    @#include "simpleexamplewidget.h"
    #include "ui_simpleexamplewidget.h"
    #include <QPaintDevice>
    #include <QPaintEvent>
    #include <QPainter>
    #include <windows.h>
    #include <QTimer>
    #include <ball.h>

    Ball b;

    SimpleExampleWidget::SimpleExampleWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SimpleExampleWidget)
    {
    ui->setupUi(this);
    }

    SimpleExampleWidget::~SimpleExampleWidget()
    {
    delete ui;
    }

    void SimpleExampleWidget::updateT(){
    QPainter p(this);
    p.setRenderHint(QPainter::Antialiasing, true);
    p.setPen(QPen(Qt::black, 12, Qt::DashDotLine, Qt::RoundCap));
    p.setBrush(QBrush(Qt::green, Qt::SolidPattern));
    if (b.counter < 10){
    p.drawEllipse(b.x,b.y,400,240);
    b.x+=5;
    b.y+=5;
    b.counter++;
    }
    }

    void SimpleExampleWidget::draw(){
    QTimer *timer = new QTimer;

    b.x = 80;
    b.y = 80;
    b.counter = 0;
    
    connect(timer, SIGNAL(timeout()), this, SLOT(updateT()));
    timer->start(50);
    

    }
    @

    SimpleExampleWidget.h
    @#ifndef SIMPLEEXAMPLEWIDGET_H
    #define SIMPLEEXAMPLEWIDGET_H

    #include <QWidget>
    #include <QPainter>
    #include <QPaintEvent>
    #include <QImage>
    #include <QImageReader>

    namespace Ui {
    class SimpleExampleWidget;
    }

    class SimpleExampleWidget : public QWidget
    {
    Q_OBJECT

    public:
    explicit SimpleExampleWidget(QWidget *parent = 0);
    ~SimpleExampleWidget();
    void draw();
    virtual void paintEvent(QPaintEvent *event){
    draw();
    }

    protected slots:
    void updateT();

    private:
    Ui::SimpleExampleWidget *ui;
    };

    #endif // SIMPLEEXAMPLEWIDGET_H
    @

    Thanks in advance!

    Pethor



  • 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":http://doc.qt.nokia.com/4.7-snapshot/animation-overview.html. 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.



  • [quote author="srikanthsombhatla" date="1309362551"]
    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.[/quote]

    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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.