PDA

View Full Version : Painter not active!



Caius Aérobus
28th March 2006, 22:58
Hi,
I have written a simple program that (try to:-)) draws a simple triangle on a PainterDevice. The drawing occurs in a paintEvent() routine but I get the following errors at runtime:
1) a message like "painter can only be initialized as a response to a paintEvent". Ok but my paintings are indeed in the paintEvent() routine, so what?
2) another message "painter is not active" BUT if I add a this->painter.begin(this) I get a message "painter is already active".
What is important is that nothing is drawn, which is my problem now.
A last question: how can I draw that spline with Qt4???
Could anybody help?
Thanks in advance.
Below is my code (can send the complete archive if necessary).


///////////////////////////////////////////////////////////////////////////////
// File : vadSpline.h //
///////////////////////////////////////////////////////////////////////////////


#ifndef _VAD_SPLINE_H
#define _VAD_SPLINE_H

#include <vadVisualization.h>

#define XSIZE 400
#define YSIZE 400

/** vadSpline est un exemple de classe pour la visualisation d'informations
dans le projet de VAD, qui implemente le dessin d'une spline.
*/
class vadSpline : public vadVisualization
{
Q_OBJECT

public:
vadSpline(QAbstractItemModel *model, vad *app=NULL, QWidget *parent=NULL, int xsize=XSIZE, int ysize=YSIZE, char *name=NULL, int debug=0);

protected slots:
void paintEvent(QPaintEvent *e);

private:
QPolygon polygon;
};

#endif

///////////////////////////////////////////////////////////////////////////////
// File : vadSpline.cxx //
///////////////////////////////////////////////////////////////////////////////


#include "vadSpline.h"

vadSpline::vadSpline(QAbstractItemModel *model, vad *app, QWidget *parent, int xsize, int ysize, char *name, int debug)
: vadVisualization(model, app, parent, xsize, ysize, name, debug)
{
this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOf f);
this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff) ;
this->show();
}

void
vadSpline::paintEvent(QPaintEvent *event)
{
this->polygon.setPoints(3,
this->model()->data(this->model()->index(0, 0)).toInt(),
this->model()->data(this->model()->index(0, 1)).toInt(),
this->model()->data(this->model()->index(1, 0)).toInt(),
this->model()->data(this->model()->index(1, 1)).toInt(),
this->model()->data(this->model()->index(2, 0)).toInt(),
this->model()->data(this->model()->index(2, 1)).toInt()
);
printf("painter active ? %d\n", this->painter->isActive() ? 1 : 0);
this->painter->setWindow(0, 0, 100, 100);
this->painter->drawPolygon(this->polygon);
}




///////////////////////////////////////////////////////////////////////////////
// File : vadVisualization.h //
///////////////////////////////////////////////////////////////////////////////


#ifndef _VAD_VISUALIZATION_H
#define _VAD_VISUALIZATION_H

#include <qabstractitemview.h>
#include <qpainter.h>
#include <visCore.h>
//#include "vad.h"

#define SIZE 400

//class vad;
#define vad QApplication

/** vadVisualization est la classe generique pour la visualisation
d'informations dans le projet de VAD.
Le principe retenu est celui du mapping de variables sur 1, 2 ou 3
axes. Ces axes ne sont pas obligatoirement les axes d'un repère nD
classique et chaque sous-classe est libre d'utiliser ce mapping a
sa facon, y compris de ne pas l'utiliser si ce n'est pas approprie.
L'objectif etait de factoriser ici certaines fonctionnalites communes
a la plupart des techniques de visualisation d'information, afin
d'asssurer coherence et gain de temps pour les developpeurs.
L'affectation des variables aux axes est effectuee par les methodes
SetXdimension(), SetYdimension() et SetZdimension().
*/
class vadVisualization : public QAbstractItemView, public visCore
{
Q_OBJECT

public:
vadVisualization(QAbstractItemModel *model, vad *app=NULL, QWidget *parent=NULL, int xsize=SIZE, int ysize=SIZE, char *name=NULL, int debug=0);

/// Acces a l'application.
visGetMacro(Vad, vad *);

protected:
/// Les fonctions ci-dessous sont des pures virtuelles, qu'il est donc necessaire de definir.
/// Pour l'instant leur definition est plus que sommaire, en fait uniquement dans le but de passer la compilation.
/// Voir la doc de Qt pour les definitions.
QRect visualRect(const QModelIndex &index) const {
return QRect(0, 0, this->width(), this->height());
}
void scrollTo(const QModelIndex &index, QAbstractItemView::ScrollHint hint=QAbstractItemView::EnsureVisible) {};
QModelIndex indexAt(const QPoint&) const {
return QModelIndex();
};
QModelIndex moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers) {
return QModelIndex();
};
int horizontalOffset() const {return 0;};
int verticalOffset() const {return 0;};
bool isIndexHidden(const QModelIndex &index) const {return FALSE;};
void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags) {};
QRegion visualRegionForSelection(const QItemSelection &selection) const {
return QRect(0, 0, this->width(), this->height());
};

/// Un painter pour le dessin.
QPainter *painter;
};

#endif


///////////////////////////////////////////////////////////////////////////////
// File : vadVisualization.cxx //
///////////////////////////////////////////////////////////////////////////////


#include "vadVisualization.h"

#define SUBFRAMEMARGIN 2

vadVisualization::vadVisualization(QAbstractItemMo del *model, vad *app, QWidget *parent, int xsize, int ysize, char *name, int debug)
: QAbstractItemView(parent)
{
this->setModel(model);
this->SetDebug(debug);
// la taille est determinee par l'application au sein de laquelle la visualisation s'insere
// sinon sa taille est determinee par les parametres d'initialisation
// this->Trace("1 size : %d %d", this->width(), this->height());
// if (app == NULL)
this->QWidget::setFixedSize(QSize(xsize, ysize));
// else
// app->Register(this);
// this->Trace("2 size : %d %d", this->width(), this->height());
// le style des fenetres
this->setFrameStyle(QFrame::Raised | QFrame::Panel);
this->setLineWidth(SUBFRAMEMARGIN);
// this->SetVad(app);
// this->Trace("3 size : %d %d", this->width(), this->height());
this->painter = new QPainter(this);
}

jacek
28th March 2006, 23:21
You should create QPainter inside paintEvent().

Caius Aérobus
29th March 2006, 11:40
Hi,
that was the first implementation I had made. I have once again modified the code so as to create the painter within the paintEvent() routine, the new code and the runtime error message are copy pasted below:

///////////////////////////////////////////////////////////////////////////////
// File : vadSpline.cxx //
// Author : Wilfrid LEFER //
// Comment : Exemple de classe concrete pour la visualisation dans //
// VAD //
// Related file : vadSpline.h //
// Master Technologies de l'Internet - VAD - 2006 //
///////////////////////////////////////////////////////////////////////////////


#include "vadSpline.h"

vadSpline::vadSpline(QAbstractItemModel *model, vad *app, QWidget *parent, int xsize, int ysize, char *name, int debug)
: vadVisualization(model, app, parent, xsize, ysize, name, debug)
{
this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOf f);
this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff) ;
this->show();
}

void
vadSpline::paintEvent(QPaintEvent *event)
{
this->polygon.setPoints(3,
this->model()->data(this->model()->index(0, 0)).toInt(),
this->model()->data(this->model()->index(0, 1)).toInt(),
this->model()->data(this->model()->index(1, 0)).toInt(),
this->model()->data(this->model()->index(1, 1)).toInt(),
this->model()->data(this->model()->index(2, 0)).toInt(),
this->model()->data(this->model()->index(2, 1)).toInt()
);
QPainter painter(this);
printf("painter active ? %d\n", painter.isActive() ? 1 : 0);
painter.setWindow(0, 0, 100, 100);
painter.drawPolygon(this->polygon);
}


///////////////////////////////////////
Error message at run time
//////////////////////////////////////

QPainter::begin: Widget painting can only begin as a result of a paintEvent
painter active ? 0
QPainter::setWindow(), painter not active
QPainter::begin: Widget painting can only begin as a result of a paintEvent
painter active ? 0
QPainter::setWindow(), painter not active


What is surprising is that the painter is not active (painter.isActive() return FALSE) but if I add a painter.begin(this) command just after the painter has been created I get another error "painter is already active"!
So what does the message "QPainter::begin: Widget painting can only begin as a result of a paintEvent" mean? Is it a mistake in the way I define the paintEvent() slot? Should I connect this slot with any signal explicitely?
Regards.

jacek
29th March 2006, 13:19
Is it a mistake in the way I define the paintEvent() slot?
paintEvent() is not a slot, but a normal virtual method. Maybe you invoke it somewhere yourself?

Caius Aérobus
29th March 2006, 16:33
No, I do not invoke paintEvent() anywhere. I have tried to declare it as public slot, public, virtual or non virtual, nothing change.
I can send you the complete source if you want.

jacek
29th March 2006, 17:07
The last snippet of code looks OK. Try grepping your sources --- maybe there is another QPainter somewhere.

Caius Aérobus
30th March 2006, 15:39
No, just one painter but I have fixed the problem: the painter creation line must be:
QPainter painter(this->viewport());
instead of:
QPainter painter(this);
I do not know why it is necessary to refer to the viewport here, may be because I invoke setWindow()?
Anyway, thanks for having spent time to help me.
Regards.

jacek
30th March 2006, 15:44
I do not know why it is necessary to refer to the viewport here, may be because I invoke setWindow()?
Does this vadSpline class inherit QAbstractScrollArea?

From Qt docs:
void QAbstractScrollArea::paintEvent ( QPaintEvent * event ) [virtual protected]
This event handler can be reimplemented in a subclass to receive paint events (passed in event), for the viewport() widget.
Note: If you open a painter, make sure to open it on the viewport().