Roby
Roby

Reputation: 2061

QT add Item trigger redraw, not freezing

i'm using QT for the first time and got some problems with refreshing the GUI while adding elements.

The Code looks like:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

   PObj obj;
   MainWindow mw;
   qRegisterMetaType<std::string>();

   QObject::connect(&obj, SIGNAL(setText(std::string const&)),
                    &mw, SLOT(appendText(std::string const&)));

   QFuture<void> f1 = QtConcurrent::run(&obj, &PObj::process);
   mw.show();

    f1.waitForFinished();

    return a.exec();
}

With the PObj::process definition:

void PObj::process()
{
for(; ;)
{
    sleep(1);

    //do work and set text
     std::string text = "bla";
     emit setText( text );
}
}

And the MainWindow::appendText slot:

void MainWindow::appendText(std::string const& str )
{
    ui->listWidget->addItem(QString::fromStdString(str));
}

I've tried placing qApp->processEvents() ,QCoreApplication::processEvents(); ... running wit future in the ThreadPool.

I thought running them with Concurrent::run is enough ?

UPDATE:

The question is, why the GUI isnt refreshed every second a new item is added ?

Upvotes: 0

Views: 70

Answers (1)

hyde
hyde

Reputation: 62777

The f1.waitForFinished(); calls blocks until f1 is finished, as the name implies. This will never happen because you have the infinite loop. So your code will never get to main loop. You can't block the main thread like that! In general, avoid any WaitForXxxx() methods, especially the GUI thread.

Also, you have no way of stopping the process(); anyway, so waiting for it to finish doesn't make any sense... You might want to add a way to tell it to stop (such as atomic variable) but anyway, to fix your problem, simply remove the f1.waitForFinished(); line.

To terminate the task nicely, try adding QAtomicInt flag (not volatile boolean, it won't do), and then change the code like this:

Add member variable to PObj (should make it private and add setter):

    QAtomicInt termianteFlag;

Change main like this:

int main(int argc, char *argv[])
{
    ///snip

    QFuture<void> f1 = QtConcurrent::run(&obj, &PObj::process);
    mw.show();

    int ret = a.exec();
    f1.terminateFlag = 1; // change this to setter method
    f1.waitForFinished(); // this is not ideal, will wait for up to a second before exit

}

and

void PObj::process()
{
    while(!terminateFlag)
    {
        sleep(1);

        //do work and set text
         std::string text = "bla";
         emit setText( text );
    }
}

Upvotes: 0

Related Questions