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?


  • Qt Champions 2016

    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();
      }
    };
    

  • Moderators

    Apparently it's a problem in setOverrideCursor and not in the dialog. You can change the dialog to something like QMessageBox::warning() or even winapi's MessageBox() 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.


  • Qt Champions 2016

    @Justin-Sayne

    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.


  • Moderators

    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


  • Moderators

    Oh, then all that's left is to workaround it and wait for a fix or fix it and submit a patch ;)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.