PDA

View Full Version : qApp->processEvents() question QWidget/QDialog



patrik08
17th May 2007, 12:28
I have two mysql connection on QMainWindow to load

i call a waiting dialog on this way:

Preload *waiter = new Preload(0,tr("Connect to host %1").arg(OneVar["dbhost1"]));
waiter->show();
/// waiter->exce();
qApp->processEvents();

/* Preload( int millisec to self close or 0 null to command close ,texttodisplay); */




if i switsch Preload to QDialog the progess bar running from 0-100 and back
just to mysql is connected .. and
i close preload

waiter->SettoClose(); and QDialog stay open ... infinite ... to wait exce int ....

if i switsch Preload to QWidget is open and close
but the progess bar stay on start and event is not processed by calling qApp->processEvents() why?








class Preload : public QWidget
{
Q_OBJECT
//
public:
Preload( int msec , const QString tex );
void SettoClose();
protected:
QPixmap display;
QString textd;
int timeemust;
bool selfclose;
int r_start;
int r_stop;
int r_status;
void paintEvent(QPaintEvent *e);
////void resizeEvent( QResizeEvent * );
private:
signals:
public slots:
void Increment();


Preload::Preload( int msec , const QString tex )
{
//////////QApplication::setOverrideCursor(QCursor(Qt::WaitCu rsor));
display = QPixmap(":/img/about_as_image.png");
textd = tex;
if (msec !=0) {
selfclose = true;
timeemust = msec;
} else {
selfclose = false;
timeemust = 1200;
}
QRect screenSize = qApp->desktop()->availableGeometry();
setWindowFlags ( Qt::Popup );
///////////qDebug() << "### screenSize -> " << screenSize;
r_start = 33;
r_status = r_start;
r_stop = 469;
////////////display = QPixmap("test.png");
QSize actual_result = display.size();
resize(actual_result);
qApp->processEvents();
Increment();
qApp->processEvents();

}

void Preload::paintEvent(QPaintEvent *e)
{
/////qDebug() << "### nullimage -> " << display.isNull();
QColor textColor = QColor(147,147,147);
QColor fillrectcolor = Qt::red;
QColor shapepicture = Qt::white;
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.drawPixmap(0,0,display);
QPen pen;
pen.setStyle( Qt::SolidLine );
pen.setWidth( 3 );
pen.setColor(fillrectcolor);
painter.setPen( pen);
painter.drawLine (QPoint(r_start,96),QPoint(r_status,96));
pen.setWidth( 2 );
pen.setColor(textColor);

QFont f( "arial", 12, QFont::Bold );
painter.setFont( f );
painter.setPen( pen);

QFontMetrics fm = painter.fontMetrics();
int largo = fm.width(textd);
painter.drawText(QPointF((display.width() / 2) - (largo / 2),118),textd);


}
void Preload::SettoClose()
{
selfclose = true;
close();
}

void Preload::Increment()
{

if (r_status > r_stop) {
if (selfclose) {
close();
return;
} else {
r_status = r_start;
}
}

int distance = r_stop - r_start;
int piesesec = timeemust / distance; /* 100% */
r_status = r_status + 1;
update();
QTimer::singleShot(piesesec, this, SLOT(Increment()));
qApp->processEvents();
}

marcel
17th May 2007, 17:58
I am sorry, but it is really, really hard to understand your post...
One thing: you're calling processEvents in unneeded places. Your dialog is not modal( you show it with show(), not exec() ).

Also, in SettoClose, just make selfclose = true and let it close itself in Increment ( because selfclose will be true ). And what is with those constants( 469, etc )?

And if status > stop, then you start again. Is this what you want?

Perhaps you can explain better what you are trying to achieve.
While the preload is active, do you want to be able to interact with it's parent window?

patrik08
17th May 2007, 18:43
I
Perhaps you can explain better what you are trying to achieve.
While the preload is active, do you want to be able to interact with it's parent window?


i try to have a mix from QSplashScreen && QProgressDialog && a benchmark to stop time
how long mysql is connect on remote host....

if i set the image on a QWidget progress not run if a QDialog progress run && all other process stop .... I solved now and i emit progress from a QThread ...
is not clean but run.... so all other function can continue to run ....

and red line continue progress just as mysql is connect...




void ProduceWait::run()
{
setTerminationEnabled(true);
qDebug() << "### QThread run start ------------------------------- ";
if (sconnect) {
while( subsection ) {
sai++;
msleep (10);
//////////////waiter->Increment();
qDebug() << "### QThread running prim ..." << sai << " text." << text;
emit TimeStatusQui(); /* progess continue */

if (!sconnect && sai < 100) {
/* display minimal time progress ... 3.5 sec*/
bool incanna = true;
int lastsai = sai;
while( subsection ) {
sai++;
qDebug() << "### QThread running slave ..." << sai << " text." << text;
msleep (10);
emit TimeStatusQui(); /* progess continue */

if (sai > 350) {
qDebug() << "### QThread stop a ................................";
emit statusMessage(tr("Total %1 msec. to %2.").arg(lastsai * 10).arg(text));
terminate();
wait(10);
incanna = false;
return;
}

}
} else if (!sconnect) {
qDebug() << "### QThread stop b ................................";
emit statusMessage(tr("Total %1 msec. to %2.").arg(sai * 10).arg(text));
terminate();
wait(10);
return;
} else if (sai > 10000) {
qDebug() << "### QThread stop c ................................";
emit statusMessage(tr("Time out to %2.").arg(text));
terminate();
wait(10);
return;
}
}

} else {
qDebug() << "### QThread stop ................................";
terminate();
wait(10);
}
}

marcel
17th May 2007, 18:49
For QWidget try setWindowFlags( Qt::Widget | Qt::WindowStaysOnTopHint ).

By the way, whay aren't you using a QSplashScreen? You have the drawContents function in which you can custom draw and make it look just as the dialog is looking now.

patrik08
17th May 2007, 19:21
For QWidget try setWindowFlags( Qt::Widget | Qt::WindowStaysOnTopHint ).

By the way, whay aren't you using a QSplashScreen? You have the drawContents function in which you can custom draw and make it look just as the dialog is looking now.


O ye.. i say that is possibel to draw on QSplashScreen ... to display progress bar inside QSplashScreen and signal and minimal time to stay open .....
To make all this or subclass QSplashScreen is easy make a QWidget from zero...

The problem on QSplashScreen is the minimal time to display ... whitout a QThread...

on main.cpp void i start :


Gui_Main *w = new Gui_Main();
w->setWindowTitle( _PROGRAM_TITLE_ );
w->hide();



if mysql is connect or timeout Gui_Main is show.. the effect is same as QSplashScreen and i can display on minimal time x..

many roads go to Rome ... and now i am happy to write my first QThread

I can only not understand how handle a QThread whit exec inside run().. like a sqlquery




void Gui_Main::WaitConnectEnd( QString txt )
{
quiwaiter->hide();
quiwaiter->close();
quiwaiter->deleteLater();
show();
Status_MSG(txt);
cannino = 0; /* reset time */
}

void Gui_Main::AIncrement()
{
cannino++; /* each 10 msec... one */
QString st = tr("Master Connection on host %1 - check %2").arg(OneVar["dbhost1"]).arg(cannino);
quiwaiter->Increment();
quiwaiter->SetText( st );
quiwaiter->setFocus ( Qt::MouseFocusReason );
hide();
}

marcel
17th May 2007, 19:30
exec() starts the thread's event loop.

You need an event loop in a thread only if:
- you connect signals from other threads to slots in your thread - this is because of queued connection - the signals emitted from other threads will actually be posted as events in your thread's event loop.
- you use a QTimer - because it will post events in the thread that created it.
- you use custom events and post them in your thread.

If you don't do any of these then I suggest dropping the exec().

ALSO, about using terminate inside run():


Warning: This function is dangerous and its use is discouraged. The thread can be terminate at any point in its code path. Threads can be terminated while modifying data. There is no chance for the thread to cleanup after itself, unlock any held mutexes, etc. In short, use this function only if absolutely necessary. Termination can be explicitly enabled or disabled by calling QThread::setTerminationEnabled (http://www.qtcentre.org/forum/qthread.html#setTerminationEnabled)(). Calling this function while termination is disabled results in the termination being deferred, until termination is re-enabled. See the documentation of QThread::setTerminationEnabled (http://www.qtcentre.org/forum/qthread.html#setTerminationEnabled)() for more information.
Therefore I suggest using a flag ( for example mFinished - volatile bool ), that you test in your loop conditions. Instead of calling terminate you can set mFinished to true, and the thread will exit on its own, when it first encounters the condition.

And you may wanna make good use of the QThreaf::finished signal. This is emitted when a thread is finished - so then you are absolutely sure that the thread exited run().

Regards