<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Beware of nested event loops]]></title><description><![CDATA[<p dir="auto">I already heard before to not use nested event loops if it can be avoided. Something strange might happen. After decades of Qt development I have now finally run into a problem with nested event loops.</p>
<p dir="auto">How do we get nested event loops? Let's start with a main window and let it create a dialog. Something like this:</p>
<pre><code>void MainWindow::some_menu_entry_triggered()
{
    QDialog dlg(this);
    ... // set up dialog
    dlg.exec(); // that's how I usually start a dialog (maybe check for returned value)
}
</code></pre>
<p dir="auto">Now, I put in that first dialog a button, that when clicked opens a second dialog. And to keep everything clean, I hide the first dialog for as long as the second is open. So, within <code>some_menu_entry_triggered()</code> I might have something like this:</p>
<pre><code>connect(dlg_button, &amp;QPushButton::clicked, this,
        [&amp;]()
        {
            QDialog dlg2(this);
            dlg.hide();
            dlg2.exec();
            dlg.show(); // nested event loop fail!
        });
</code></pre>
<p dir="auto">The first dialog will never again show up. However, it is still modal and will block all interaction with the main window! And the problem is with nested event loops.</p>
<p dir="auto">This problem arises with the following programming pattern (which I followed because it is used extensively in our software (maybe also because it was ported from wxWidgets at some point)):</p>
<pre><code>if(dlg.exec() == QDialog::Accepted)
{
    // do stuff
}
</code></pre>
<p dir="auto">For other reasons I already had to handle the click on the OK button differently by connecting to the <code>QDialog::accepted</code> signal. That is why <code>if(dlg.exec() == QDialog::Accepted)</code> already degenerated to just <code>dlg.exec()</code>. If you start fresh, you should always connect to <code>QDialog::accepted</code>.</p>
<p dir="auto"><code>dlg.exec()</code> can be replaced by <code>dlg.show()</code> (and <code>dlg.setModel(true)</code> if that is what you really want). But, this introduces a separate problem: The lifetime of the <code>dlg</code> variable is too short. In general, I prefer to have my lifetimes automatically managed by putting variable on the stack. In this case we have to do this differently:</p>
<pre><code>QDialog *dlg = new QDialog(this);
connect(dlg, &amp;QDialog::finished, dlg, &amp;QDialog::deleteLater);
// further dlg setup
dlg-&gt;show();
</code></pre>
<p dir="auto">This is at least how I have solved the nested event loop problem (using <code>show()</code> instead of <code>exec()</code> for both dialogs).</p>
<p dir="auto">So, here you have a real world example when nested event loops fail.</p>
]]></description><link>https://forum.qt.io/topic/164910/beware-of-nested-event-loops</link><generator>RSS for Node</generator><lastBuildDate>Sat, 03 Oct 2026 22:26:23 GMT</lastBuildDate><atom:link href="https://forum.qt.io/topic/164910.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 21 Jul 2026 07:19:23 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Beware of nested event loops on Fri, 04 Sep 2026 05:48:11 GMT]]></title><description><![CDATA[<p dir="auto">you cant call run() run() simply</p>
]]></description><link>https://forum.qt.io/post/839976</link><guid isPermaLink="true">https://forum.qt.io/post/839976</guid><dc:creator><![CDATA[sales99]]></dc:creator><pubDate>Fri, 04 Sep 2026 05:48:11 GMT</pubDate></item><item><title><![CDATA[Reply to Beware of nested event loops on Sun, 26 Jul 2026 09:55:43 GMT]]></title><description><![CDATA[<pre><code>void MainWindow::on_pushButton_clicked()
{
    qDebug()&lt;&lt;"begin 1";
    QEventLoop loop1;
    QDialog dlg1;
    dlg1.setWindowTitle("dlg1");
    dlg1.setLayout(new QVBoxLayout());
    QPushButton *button = new QPushButton("Click");
    dlg1.layout()-&gt;addWidget(button);

    QObject::connect(&amp;dlg1, &amp;QDialog::finished, &amp;loop1, &amp;QEventLoop::quit);
    QObject::connect(button, &amp;QPushButton::clicked, &amp;dlg1,
                     [&amp;]()
                     {
                         qDebug()&lt;&lt;"begin 2";
                         dlg1.hide();
                         QDialog dlg2;
                         dlg2.setWindowTitle("dlg2");
                         dlg2.exec();
                         dlg1.show();
                         qDebug()&lt;&lt;"end 2";
                     });

    dlg1.open();
    loop1.exec();
    qDebug()&lt;&lt;"end 1";
}
</code></pre>
]]></description><link>https://forum.qt.io/post/839386</link><guid isPermaLink="true">https://forum.qt.io/post/839386</guid><dc:creator><![CDATA[gongjianbo]]></dc:creator><pubDate>Sun, 26 Jul 2026 09:55:43 GMT</pubDate></item><item><title><![CDATA[Reply to Beware of nested event loops on Wed, 22 Jul 2026 08:04:53 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/simonschroeder">@<bdi>SimonSchroeder</bdi></a> said in <a href="/post/839305">Beware of nested event loops</a>:</p>
<blockquote>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/jonb">@<bdi>JonB</bdi></a> Just one wild guess what's different: In my case the event loop is also already running. You are doing a.exec() only after dlg1.exec(). So, this is one less nesting level.</p>
</blockquote>
<p dir="auto">FWIW, and for completeness, I changed above code from running <code>dlg1.exec();</code> immediately before <code>a.exec()</code> to</p>
<pre><code>QTimer::singleShot(3000, [&amp;dlg1]() { dlg1.exec(); } );
</code></pre>
<p dir="auto">Behaviour is same: dialogs hide and show as expected, no missing "re-show".</p>
<p dir="auto">It is true that I am Linux and Qt6 while you are Windows and Qt5.  I don't know if one of those is the difference.</p>
]]></description><link>https://forum.qt.io/post/839307</link><guid isPermaLink="true">https://forum.qt.io/post/839307</guid><dc:creator><![CDATA[JonB]]></dc:creator><pubDate>Wed, 22 Jul 2026 08:04:53 GMT</pubDate></item><item><title><![CDATA[Reply to Beware of nested event loops on Wed, 22 Jul 2026 06:29:51 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/jonb">@<bdi>JonB</bdi></a> Just one wild guess what's different: In my case the event loop is also already running. You are doing <code>a.exec()</code> only after <code>dlg1.exec()</code>. So, this is one less nesting level.</p>
<p dir="auto">But, what I didn't mention is that I'm on Windows 11 and still using Qt 5.13.2. (We don't often change Qt versions because we compile Qt statically ourselves (and also Qwt). It takes up a lot of time and software development is not our primary business.)</p>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/jksh">@<bdi>JKSH</bdi></a> Kind of looks like essentially the same problem: The final show event seems to get lost when the inner most event loop is destroyed.</p>
]]></description><link>https://forum.qt.io/post/839305</link><guid isPermaLink="true">https://forum.qt.io/post/839305</guid><dc:creator><![CDATA[SimonSchroeder]]></dc:creator><pubDate>Wed, 22 Jul 2026 06:29:51 GMT</pubDate></item><item><title><![CDATA[Reply to Beware of nested event loops on Tue, 21 Jul 2026 09:01:32 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/simonschroeder">@<bdi>SimonSchroeder</bdi></a><br />
The following code:</p>
<pre><code>
#include &lt;QApplication&gt;
#include &lt;QBoxLayout&gt;
#include &lt;QDialog&gt;
#include &lt;QPushButton&gt;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QDialog dlg1;
    dlg1.setWindowTitle("dlg1");
    dlg1.setLayout(new QVBoxLayout());
    QPushButton *button = new QPushButton("Click");
    dlg1.layout()-&gt;addWidget(button);

    QObject::connect(button, &amp;QPushButton::clicked, &amp;dlg1,
            [&amp;]()
            {
                QDialog dlg2(&amp;dlg1);
                dlg1.setWindowTitle("dlg2");
                dlg1.hide();
                dlg2.exec();
                dlg1.show(); // nested event loop fail!
            });

    dlg1.exec();
    return a.exec();
}
</code></pre>
<p dir="auto">works fine for me.  Ubuntu 24.04, Qt  6.4.2.    I press the button, see the second dialog, close it, and the first dialog reappears.  I can remove <code>&amp;dlg1</code> from being the argument to <code>dlg2</code>'s constructor and it still works.  In what significant way does your situation differ from this?</p>
]]></description><link>https://forum.qt.io/post/839275</link><guid isPermaLink="true">https://forum.qt.io/post/839275</guid><dc:creator><![CDATA[JonB]]></dc:creator><pubDate>Tue, 21 Jul 2026 09:01:32 GMT</pubDate></item><item><title><![CDATA[Reply to Beware of nested event loops on Tue, 21 Jul 2026 07:34:22 GMT]]></title><description><![CDATA[<p dir="auto">Here's another way to cause a fail: <a href="https://qt-project.atlassian.net/browse/QTBUG-116984" target="_blank" rel="noopener noreferrer nofollow ugc">https://qt-project.atlassian.net/browse/QTBUG-116984</a></p>
]]></description><link>https://forum.qt.io/post/839266</link><guid isPermaLink="true">https://forum.qt.io/post/839266</guid><dc:creator><![CDATA[JKSH]]></dc:creator><pubDate>Tue, 21 Jul 2026 07:34:22 GMT</pubDate></item></channel></rss>