New widget not displayed until slot function returns.
-
I have a situation where some code specified in a slot can potentially create a QWidget and show it.
But it seems that the widget is not displayed until that function returns.
(I call the show method, but that doesn't help)Is this a design decision?
How can I work around this problem ? -
Hi,
[quote author="manasij7479" date="1422710589"]Is this a design decision?[/quote]Yes. The GUI won't update (so your widget won't show) until your function returns to the event loop.
[quote author="manasij7479" date="1422710589"]How can I work around this problem ?[/quote]If you want a quick hack, add QApplication::processEvents() into the loop in your slot.
However, the more robust method is to run your long function in a separate thread, and emit signals to create + show a QWidget.
-
The hack worked nicely, thanks.
For a long term solution, I tried this for creating the window.
I made a pointer to the mian window global and connected to its create slot defined as follows:
@void MainWindow::create(spider::GraphValue* g, spider::Layoutspider::Graph* l)
{
spider::WindowValue* winv = static_castspider::WindowValue*(QObject::sender());
winv->data = new spider::WindowUI(g,l);
winv->data->show();
}@But the widget does not show up and I still need to call that processEvents function.
So it seems I will have to stick with QApplication::processEvents().
Is there much performance penalty involved ? -
Hi,
Can you post your original implementation ?
On a side note, you should use qobject_cast and not static_cast when dealing with QObject derived class.
-
This code is invoked indirectly from a slot:
@
// window creation goes here
graph::BreadthFirstSearch<Graph> bfs(*getg(args[0])->data, s);
bfs.setp4([&](const std::string& x,const std::string& y)
{
g->insertVertex(y);
g->insertEdge(x, y, 1);
gv->changeCallback();//this emits something that causes the window to changestd::this_thread::sleep_for (std::chrono::milliseconds(1000)); return true;
});
bfs();@Only after putting QApplication::processEvents() inside the lambda, the window is updated whenever signalled.
-
Do you by any chance have a 1 second delay for the widget to show ?
-
Nope.
It appeared after the whole process was finished and the slot this is called from returns.
I tested this in the following way.
The slot actually invokes an interpreter for a simple language.
So I put an infinite loop in the text box after the call to the display funcion.
And the window never appeared. -
[quote author="manasij7479" date="1422739992"]This code is invoked indirectly from a slot:
@
// window creation goes here
graph::BreadthFirstSearch<Graph> bfs(*getg(args[0])->data, s);
bfs.setp4([&](const std::string& x,const std::string& y)
{
g->insertVertex(y);
g->insertEdge(x, y, 1);
gv->changeCallback();//this emits something that causes the window to changestd::this_thread::sleep_for (std::chrono::milliseconds(1000)); return true;
});
bfs();@
[/quote]Does that code run in the GUI thread or the worker thread? -
GUI thread.
My MainWindow class has an object of my 'Runtime'.
That runtime has a functioneval
.
The main window has a slotrun
:
@void MainWindow::run(const QString&)@which calls rt->eval(input);
The above code is somewhere invoked from eval.The Runtime does not create other threads.
The problem was that the extra window created in eval did not show up until the slot
run
finished executing.
processEvents fixed that.If you have time, (and have Linux and KDE libs installed) you can build my code if interested.
https://github.com/manasij7479/spider
Switch to the branch 'qt'.
Try out example inputs given here:
https://github.com/manasij7479/spider/blob/master/IRManual.md -
[quote author="manasij7479" date="1422785350"]GUI thread.[/quote]The GUI event loop can only process GUI events (including "show window" events) when the GUI thread is idle. If your function is running in the GUI thread, then GUI thread isn't idle so your window won't show.
QApplication::processEvents() temporarily "pauses" your function and lets the GUI event loop handle GUI events, before letting your function continue.
My first post said (emphasis added):[quote author="JKSH" date="1422725696"]the more robust method is to run your long function in a separate thread, and emit signals to create + show a QWidget.[/quote]By using a separate thread, your GUI thread can be idle even when your other function is running.
Note: "I want to keep my GUI responsive while calling a long-running function" is one of the basic reasons why people use multithreading.