You are not logged in.

Dear visitor, welcome to QtForum.org. If this is your first visit here, please read the Help. It explains in detail how this page works. To use all features of this page, you should consider registering. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

1

Tuesday, September 19th 2006, 6:21pm

QPaintEvent problem in QT4

I have a multi-thread application wrote in Qt3, now I want to move it to Qt4. But I got a error with paintEvent. The demo code is like this:

.h file:

class QtWidget;

class SThread : public QThread
{
public:
void SetMainWnd(QtWidget *pMainWnd);
public:
void run();
QtWidget *m_pMainWnd;
};


class QtWidget : public QWidget
{
Q_OBJECT

public:
QtWidget( QWidget* parent = 0, const char* name = 0 );
~QtWidget();
void closeEvent ( QCloseEvent * e );
void paintEvent ( QPaintEvent * e );

SThread m_sThread;
bool m_bRunThread;
QString m_str;

};

.cpp file:

void SThread::SetMainWnd(QtWidget *pMainWnd)
{
m_pMainWnd=pMainWnd;
}

void SThread::run()
{
int i=0;
while ( 1)
{
bool bOK;
usleep(1000*1000);
if ( !m_pMainWnd->m_bRunThread)
{
break;
}
i++;
printf( "thread running \n");
qApp->lock();
m_pMainWnd->m_str.sprintf("%d",i);
QApplication::postEvent( m_pMainWnd, new QPaintEvent( m_pMainWnd->rect() ) );
qApp->unlock();
}

}

void QtWidget::paintEvent(QPaintEvent *e)
{
printf("Paint\n");
QPainter p(this);
p.drawText(20,20,this->m_str);
p.end();
}


QtWidget::QtWidget( QWidget* parent, const char* name )
: QWidget( parent, name )
{
this->m_bRunThread=true;
m_sThread.SetMainWnd(this);
this->m_sThread.start();
m_str="AAA";
}

QtWidget::~QtWidget()
{
// no need to delete child widgets, Qt does it all for us
}
void QtWidget::closeEvent ( QCloseEvent * e )
{
printf("quit widget\n");
m_bRunThread=false;
this->m_sThread.wait();
e->accept();
qApp->quit();
}

The working thread will call
QApplication::postEvent( m_pMainWnd, new QPaintEvent( m_pMainWnd->rect() ) );

to make the main widget repaint every second.

This works fine on qt3. but on qt4, the paintEvent function showed the following error message:

QPainter::begin: Widget painting can only begin as a result of a paintEvent
QPainter::end: Painter is not active, aborted


What is the right way to do it in qt4?


Thanks.
jackchen has attached the following file:
  • qt1.tar.gz (21.77 kB - 31 times downloaded - latest: Feb 6th 2013, 7:02am)

pakewak

Beginner

  • "pakewak" is male

Posts: 8

Location: Belgium

Occupation: Research assistent

  • Send private message

2

Thursday, September 21st 2006, 12:05pm

Hi,

I think you better call the repaint() or update() method of your widget, which in turn send QPaintEvents, instead of sending your own QPaintEvent.

See http://doc.trolltech.com/4.1/qwidget.html#paintEvent.

bye,

3

Thursday, September 21st 2006, 5:58pm

Thank you very much. Replacing the postEvent with update did the trick.

//QApplication::postEvent( m_pMainWnd, new QPaintEvent( m_pMainWnd->rect() ) );
m_pMainWnd->update();

But I am not sure if it's thread safe though.

The reason I want to use postEvent is because I need to update the widget from another thread and postEvent is thread safe.

I found a example in
http://doc.trolltech.com/4.1/threads-mandelbrot.html

probably the best way to do it is using slot. damn, lots of work.







Quoted

Originally posted by pakewak
Hi,

I think you better call the repaint() or update() method of your widget, which in turn send QPaintEvents, instead of sending your own QPaintEvent.

See http://doc.trolltech.com/4.1/qwidget.html#paintEvent.

bye,

4

Thursday, September 21st 2006, 10:29pm

Hi jackchen,
try to look at Qt::WA_PaintOutsidePaintEvent widget attribute. Your code above seems to be Qt3 code, since they dont have global library mutex in Qt4 and so I think you should edit QtWidget constructor code after applying step 4 from "porting to Qt4" article in Assistant so that it will set this attribute.

5

Thursday, September 21st 2006, 11:23pm

Quoted

Originally posted by sturm
Hi jackchen,
try to look at Qt::WA_PaintOutsidePaintEvent widget attribute. Your code above seems to be Qt3 code, since they dont have global library mutex in Qt4 and so I think you should edit QtWidget constructor code after applying step 4 from "porting to Qt4" article in Assistant so that it will set this attribute.


Yes, my code is Qt3 code and I want to move it to qt4 ( then to Windows Qt).


QtWidget::QtWidget( QWidget* parent, const char* name )
: QWidget( parent, name )
{
setAttribute(Qt::WA_PaintOutsidePaintEvent);
...
}

void SThread::run()
{
...
QApplication::postEvent( m_pMainWnd, new QPaintEvent( m_pMainWnd->rect() ) );
//m_pMainWnd->update();
...
}


This PaintOutsidePaintEvent does make difference, but still has problem. Now it doesn't show the error but the printed out charactors are overlayed. It didn't clear the background. Also this parameter is not supported in Windows.


From this document,
http://doc.trolltech.com/4.1/threads-mandelbrot.html

I think the safe way is using slot.

6

Friday, September 22nd 2006, 11:09am

My qt4.1.2 doc says that this parameter is not supported under MacOS X and it says nothing about Windows.
Anyway, instead of posting QPaintEvent you can post your custom event to your widget, implement QWidget::event( QEvent* ) in a proper way and call QWidget::update(...) from this event handler when your event has arrived. Think this should work even without setting additional attributes.

7

Friday, September 22nd 2006, 5:26pm

Quoted

Originally posted by sturm
My qt4.1.2 doc says that this parameter is not supported under MacOS X and it says nothing about Windows.
Anyway, instead of posting QPaintEvent you can post your custom event to your widget, implement QWidget::event( QEvent* ) in a proper way and call QWidget::update(...) from this event handler when your event has arrived. Think this should work even without setting additional attributes.


I did google for WA_PaintOutsidePaintEvent and this document
http://www.riverbankcomputing.com/Docs/P…tAttribute-enum

says it's not supported on Windows or Mac OS X. Maybe it's a old version document.


Yes, a custom event should do it. Thank you very much.

8

Friday, September 22nd 2006, 6:41pm

WA_PaintOutsidePaintEvent is only supported by a few paint engines like OpenGL. It works also with X11 today, but is recommended not to be used (see composite manager ).

To answer your initial problem: you have to use repaint/update. Otherwise your code will run outside the graphic pipeline of Qt4, that is different to Qt3, because of supporting next generation desktops with gimmicks like transparent windows ...

Uwe