PDA

View Full Version : QPainter problem - migration from qt3 [SOLVED]



tpomorsk
28th August 2006, 10:01
Hi,
I had the following code in qt3 and it worked perfectly (I removed resize and refresh procedures)
whiteboard.h


class Whiteboard : public QFrame
{
Q_OBJECT
public:
QPoint qt_currMosePos;
QPoint qt_prevMousePos;
QPen *pen;
QPainter * paint;

Whiteboard( QWidget *parent=0, const char* name = 0);
~Whiteboard()

protected:
void mouseMoveEvent(QMouseEvent *);
void mousePressEvent(QMouseEvent *);
};


whiteboard.cpp


#include "whiteboard.h"

Whiteboard::Whiteboard( QWidget *parent, const char* name) : QFrame(parent,name)
{
paint = new QPainter(this);
pen = new QPen(Qt::red,2);
paint->setPen(*pen);
this->setBackgroundMode(Qt::NoBackground);
}
Whiteboard::~Whiteboard()
{
delete paint;
}

void Whiteboard::mouseMoveEvent(QMouseEvent *e)
{
qt_currMousePos = e->pos();
paint->drawLine(qt_prevMousePos,qt_currMosePos);
qt_prevMousePos = qt_currMousePos;
}

void Whiteboard::mousePressEvent(QMouseEvent *e)
{
if(e->button() == Qt::LeftButton) {
qt_prevMousePos = e->pos();
paint->drawLine(qt_prevMousePos,qt_prevMousePos);
}
}


Basically it allows you to plot on the widget with your mouse.
I compiled it under Solaris and Linux.

Now I migrated to qt4. I ran qt3to4 and recompiled it. No problems.
But when I launch the program I cannot paint and I have the following message in the console:
QPainter::begin: Widget painting can only begin as a result of a paintEvent

What has happend? Are there some new limitations in qt4?
I know that migration from qt3 has been discussed since long time ago but I cannot find any mention of this problem.
Thanks for help

Tomek

kemp
28th August 2006, 10:08
Try to use Q3Painter. Maybe this will help.

tpomorsk
28th August 2006, 10:27
Thanks for reply.
It didn't help.
Even if I use Q3Frame and Q3Painter I still have the same message in the conosle and still I cannot paint.

Tomek

high_flyer
28th August 2006, 11:08
What has happend? Are there some new limitations in qt4?
Yes.
Well, not really limitations, but new ways to do things (and new structure)
And this:

Widget painting can only begin as a result of a paintEvent
being one of them.
read all about it here:
http://doc.trolltech.com/4.0/qt4-arthur.html

jpn
28th August 2006, 11:09
Painting using a QPainter can only take place in a paintEvent() or a function called by a paintEvent().

Something like this should be more appropriate for Qt4 (don't expect it to compile nor fully work, it's written on the fly):


Whiteboard::Whiteboard( QWidget *parent) : QFrame(parent)
{
setBackgroundMode(Qt::NoBackground);
}

void Whiteboard::mouseMoveEvent(QMouseEvent *e)
{
qt_currMousePos = e->pos();
update(); // schedule a paint event
}

void Whiteboard::mousePressEvent(QMouseEvent *e)
{
if(e->button() == Qt::LeftButton) {
qt_currMousePos = e->pos();
qt_prevMousePos = qt_currMousePos;
update(); // schedule a paint event
}
}

void Whiteboard::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
painter.setPen(QPen(Qt::red, 2));
painter.drawLine(qt_prevMousePos, qt_currMosePos);
qt_prevMousePos = qt_currMousePos;
}

tpomorsk
28th August 2006, 12:09
High_flyer,
Thanks for the link. I read it and now I understand the reason for this change.

Jpn,
Thanks for the solution. I tried it but it's too slow. The line which is drawn is not smooth enough. It's much much worse than with qt3 where QPainter could be initialized only once (in a constructor of a widget). I think that the function begin() of QPainter takes too much time.
I tried to initialize QPainter in the constructor and run only begin() in paintEvent but it's still very slow.




Whiteboard::Whiteboard( QWidget *parent) : QFrame(parent)
{
setBackgroundMode(Qt::NoBackground);
paint = new QPainter();
}

...

void Whiteboard::paintEvent(QPaintEvent *e)
{
paint->begin(this);
paint->setPen(QPen(Qt::red, 2));
paint->drawLine(qt_prevMousePos, qt_currMosePos);
qt_prevMousePos = qt_currMousePos;
paint->end();
}


Is there another way to optimize it or do I have to play with QPaintEngine?

Tomek

tpomorsk
28th August 2006, 15:35
Problem solved.
In fact paintEvent() was slow because of double-buffering, which is turned on by default in Qt4. All I had to do is to turn it off.
I used JPN's code and added the following line in the constructor of my main class (whiteboard)


this->setAttribute(Qt::WA_PaintOnScreen);

After that there is no difference in performance between qt4 and qt3.


Thanks for help,
Tomek

high_flyer
28th August 2006, 15:43
In fact paintEvent() was slow because of double-buffering, which is turned on by default in Qt4.
Thanks for pointing that out.
Another handy point to check in the future, if painting is slow. :)