I created an application in which I would like to add a loading screen when the application is opening a project because the loading of the project can be long and sometimes, the gui blocks so the user can think there is a crash.
So I tried with QThread, reading doc and "solved" examples on this forum but nothing to do, I can't make it work.
I have a MainWindow class which deals with GUI and this class is the one I create in the main function :
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Then I have : mainwindow.h
class MyThread;
class MainWindow : public QMainWindow
{
Q_OBJECT
...
private :
Controller *controller;//inherits from QObject and loads the project
QList<MyThread*> threads;
public slots :
void animateLoadingScreen(int inValue);
}
mainwindow.cpp
MainWindow::MainWindow(...)
{
controller=new Controller(...);
threads.append(new MyThread(30, this));
connect(threads[0], SIGNAL(valueChanged(int)), this, SLOT(animateLoadingScreen(int)));
}
void MainWindow::animateLoadingScreen(int inValue)
{
cout<<"MainWindow::animateLoadingScreen"<<endl;
widgetLoadingScreen->updateValue(inValue);//to update the animation
}
void MainWindow::openProject()
{
widgetLoadingScreen->show()://a widget containing a spinner for example
threads[0]->start();//I want to launch the other thread here
controller->openProject();
threads[0]->exit(0);//end of thread so end of loading screen
}
MyThread.h
class MyThread : public QThread
{
Q_OBJECT;
public:
explicit MyThread(int interval, QObject* parent = 0);
~MyThread();
signals:
void valueChanged(int);
private slots:
void count(void);
protected:
void run(void);
private:
int i;
int inc;
int intvl;
QTimer* timer;
};
MyThread.cpp
MyThread::MyThread(int interval, QObject* parent): QThread(parent), i(0), inc(-1), intvl(interval), timer(0)
{
}
void MyThread::run(void)
{
if(timer == 0)
{
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(count()));
}
timer->start(intvl);
exec();
}
void MyThread::count(void)
{
if(i >= 100 || i <= 0)
inc = -inc;
i += inc;
emit valueChanged(i);
}
When I execute the app, and click on open button which launches MainWindow::openProject(), I get :
QObject: Cannot create children for a parent that is in a different thread.
(Parent is MyThread(0x5463930), parent's thread is QThread(0x3cd1f80), current thread is MyThread(0x5463930)
MainWindow::animateLoadingScreen
MainWindow::animateLoadingScreen
....
MainWindow::animateLoadingScreen
MainWindow::animateLoadingScreen
(and here the controller outputs. and no MainWindow::animateLoadingScreen anymore so the widget loading screen is never animated during the opening of the project)
So what do I have to do, what do I have to put in MyThread class, how to link its signal to MainWindow to update the loading screen. And I think that there may be a problem with widgetLoadingScreen which is created in MainWindow so if MainWindow is blocked beacause of the opening, the widgetLoadingScreen can't be updated since it is in the thread of MainWindow which handles the GUI ?!
I read : http://www.qtcentre.org/wiki/index.php?title=Updating_GUI_from_QThread but with that one, I got error message at runtime, it's the one I use in the code I give above QObject: Cannot create children for a parent that is in a different thread. (Parent is MyThread(0x41938e0), parent's thread is QThread(0x1221f80), current thread is MyThread(0x41938e0)
I tried that too : How to emit cross-thread signal in Qt? but, even if I don't have the error message at runtime, it's the same for the animation which is not updated.
I am completely lost, and I don't think it's something difficult to do to have a loading screen in a thread while the main thread is opening a project?!