Unsolved QFileDialog::getOpenFileName messes up cursor stack?!
-
I have a slot that's directly connected to a button click (so executed in the Qt gui thread) and every time I call QFileDialog::getOpenFileName, no matter if given a parent or not, calling QApplication::setOverrideCursor anywhere afterwards won't work unless I call QApplication::processEvents after this. If I leave the call to getOpenFileName out, setOverrideCursor works perfectly fine as expected also without processEvents.
How can that be? I was debugging through the internal Qt sources and was looking if getOpenFileName in some way modifies the cursor stack but I wasn't able to find anything. Am I missing sth obvious? -
Hello,
QWidget and its subclasses are not reentrant, nor thread safe. Make sure that any call you make to the GUI part is from the GUI thread. Then, a direct connection is exactly as if you called the function yourself, so I see no reason one way to work and the other not to. Still if you could provide some source it would be helpful.Kind regards.
-
Didn't I just state in my very first sentence that everything happens in the GUI thread so multi-threading issues can completely be ruled out?
Anyway, I tried to create a minimal example and can clearly reproduce it. I created a QMainWindow in QtDesigner and just added a simple QPushButton to its central widget. The implementation looks like this:
class TestWindow : public QMainWindow, public Ui::TestWindow { Q_OBJECT public: TestWindow() : QMainWindow() { setupUi(this); } void init() { connect(pushButton, &QPushButton::pressed, this, &TestWindow::testslot); } void testslot() { // uncomment the following line and the following cursor change won't display // without a call to QApplication::processEvents, with it being commented out, // it works perfectly fine. What's the reason for this? // QFileDialog::getOpenFileName(nullptr); QApplication::setOverrideCursor(Qt::WaitCursor); QThread::currentThread()->msleep(3000); QApplication::restoreOverrideCursor(); } };
-
Apparently it's a problem in
setOverrideCursor
and not in the dialog. You can change the dialog to something likeQMessageBox::warning()
or even winapi'sMessageBox()
and it will happen too.I did not dig deep enough but it seems to be related to the fact that showing any kind of dialog/popup and then hiding it leaves the app as not active until events are processed, and this somehow prevents the cursor from being set. The call stack is a jungle so with little effort I made I wasn't able to pinpoint the issue exactly.
-
Didn't I just state in my very first sentence that everything happens in the GUI thread so multi-threading issues can completely be ruled out?
I'm just trying to help, no need to get snippy. I missed the directly part of your post, sorry. As for your problem, I've tested both the 5.5.1 and 5.6 Qt (both x64) builds I have available on my system (Debian, 4.2.0 kernel) and both work as expected. I cancel the file dialog and after a bit the cursor returns to its proper state. I did remove the
setupUi
and the form, but I don't expect that to be the problem. Here's the source I use for testing:#include <QMainWindow> #include <QVBoxLayout> #include <QPushButton> #include <QFileDialog> #include <QApplication> #include <QThread> class TestWindow : public QMainWindow { Q_OBJECT public: TestWindow() : QMainWindow() { setCentralWidget(new QWidget); QVBoxLayout * layout = new QVBoxLayout(centralWidget()); QPushButton * button = new QPushButton(centralWidget()); layout->addWidget(button); connect(button, &QPushButton::pressed, this, &TestWindow::testslot); } void testslot() { // uncomment the following line and the following cursor change won't display // without a call to QApplication::processEvents, with it being commented out, // it works perfectly fine. What's the reason for this? QFileDialog::getOpenFileName(); QApplication::setOverrideCursor(Qt::WaitCursor); QThread::currentThread()->msleep(3000); QApplication::restoreOverrideCursor(); } };
-
Good point, I should have mentioned that I'm still running under Qt 5.3.1 on Win8 MSVC x64. I'll try to link with the newest Qt libs. Which Qt verson were you using, Chris?
-
Update: Qt 5.5 also doesn't work for me.
-
I'm on Qt5.5.1, Win 10, VS2015.
It looks like a very particular scenario and not a general issue, thus easy to miss. Especially since it's related to how particular window manager works (the offending code seems to be in the windows platform plugin).I think it's agood candidate to report a bug.
-
It has already been opened multiple times and even been fixed for Qt4, see
#42117
#40122 and
#6525 -
Oh, then all that's left is to workaround it and wait for a fix or fix it and submit a patch ;)