0

I am using a third party library which takes 60-90 seconds to dynamically load several libraries. It is an unfortunate design choice, but I can't change who the built their code.

I am trying to use a QSplashScreen to at least tell the user to wait while I'm doing this one-time loading in the background. The problem is that the splash screen is not painting. I can see a window of non-painted space while the library loads. I can see the splash screen afterwards before I close it.

I looked at similar questions (e.g. Qt Splash Screen not showing) but nothing seems to resolve my problem. I have tried loading an empty QPixmap and just giving it a solid color. That doesn't show up either.

QApplication a(argc, argv);
QPixmap pxl("icon.bmp");
QSplashScreen qss(pxl);
qss.show();
qss.showMessage(QString::fromStdString("Please wait... Loading"));
a.processEvents();

MainWindow w;
//thread is blocked
w.preLoad();//this is where the lengthy process takes place
w.show();

qss.finish(&w);

I'd like to ensure that it at least paints once before I start my loading process.

------------------------EDIT-------------------------------

Let me reiterated that the call to preLoad is BLOCKING the thread. This is not an option. I have tried a separate thread for that process. I have tried with a separate thread for the splash screen as well (turning it on and then finishing whne the other thread is done). I have tried using semaphore between the two threads to accomplish this and while everything works (including the splash screen) it takes 200-800 seconds to load. That is simply not acceptable. Thus I would like to see if there is away around it from this perspective.

-------------------------Final solution--------------------------------

Thanks to the comments below I was made aware that Qt has its own threading functionality. All the problems I was seeing appear to be caused by the interplay of std::thread and Qt's own implementation.

I have a partial solution which does work. It's not as neat as it could be, but I wanted to include it in the question thread.

//in the main method code described above
MainWindow w;
w.preLoad();
while(w.IsLoading())
{
  //waiting on semaphore signaling loading is complete
  //this part could probably be done better with QThread 
  //and signals, but it is a quick fix for now
  std::this_thread::sleepfor(std::chrono::milliseconds(500));
  a.processEvents();
}
w.show();

qss.finish(&w);


//In the MainWindow class
void MainWindow::preLoad()
{
  loading=true;//semaphore to stall main thread
  QFuture<void> future = QtConcurrent::run(this, &MainWindow::LongMethod);
}

void MainWindow::LongMethod()
{
  thirdPartyLibrary.impossibleCall();
  loading=false;//this handles my semaphore
}
BSD
  • 329
  • 3
  • 13
  • what is `preLoad`? – eyllanesc Nov 01 '17 at 17:07
  • preLoad is the method which calls the third party library. That first call takes 60-90 seconds. There is no code to show you. Sufficient to say that it blocks the thread during this period. – BSD Nov 01 '17 at 17:08
  • Is it running on a secondary thread? – eyllanesc Nov 01 '17 at 17:09
  • Nope. Same thread. – BSD Nov 01 '17 at 17:10
  • 1
    I think that this task is blocking the GUI, if you have a heavy task it is advisable to execute it in a second thread obviously respecting the conditions of Qt. – eyllanesc Nov 01 '17 at 17:11
  • 1
    I recommend you read the following: http://doc.qt.io/qt-5/qtconcurrentrun.html – eyllanesc Nov 01 '17 at 17:13
  • Another option is to call between each instruction that you run in preload to: `qApp->processEvents();` – eyllanesc Nov 01 '17 at 17:14
  • @eyllanesc Why in the world is Qt implementing it's own threading system? No wonder my std::thread operations where causing havoc. The reference you gave opened up a whole new view of building an application in Qt. I'd like to give you the points for the answer. Can you put something into an answer rather than a comment? – BSD Nov 01 '17 at 17:44
  • ***Qt implementing it's own threading system?*** One reason is backward compatibility. Qt existed long before c++11. Also Qt uses signals and slots with its threading support. – drescherjm Nov 01 '17 at 18:05

1 Answers1

2

Every GUI is executed in an infinite loop, so Qt also uses it, but the blocking tasks generate that the loop is not executed correctly, showing inadequate behaviors like the one you observe.

If one wants to execute blocking tasks it is advisable to execute it in another thread for it Qt provides several possibilities:

I recommend the following link for you to choose the right option for your case.

If you want to update the GUI view with the information generated in another thread it is advisable to use signals and slots, or use QtConcurrent.

GUI Thread and Worker Thread

As mentioned, each program has one thread when it is started. This thread is called the "main thread" (also known as the "GUI thread" in Qt applications). The Qt GUI must run in this thread. All widgets and several related classes, for example QPixmap, don't work in secondary threads. A secondary thread is commonly referred to as a "worker thread" because it is used to offload processing work from the main thread.

Another way is to force the GUI to update for this we can use qApp->processEvents().

References:

eyllanesc
  • 235,170
  • 19
  • 170
  • 241