June 22, 2011

LinusA LinusA
Lab Rat
62 posts

[Solved] QFileDialog::getOpenFileName breaks message boxes etc.

Page  
1

Hi!

The following code sequence (a slot being called) causes big problems:

  1. void CMainWidget::doMain() {
  2.  //QWidget *const pParent = nullptr;
  3.  QWidget *const pParent = this;
  4.  
  5.  // check that the message box is working as expected!
  6.  QMessageBox::information(pParent, "Test Msgbox", tr("Qt Version: %1").arg(QT_VERSION_STR));
  7.  
  8.  // THIS QFILEDIALOG BREAKS SOMETHING!
  9.  // comment the next line out to see everything working normal!
  10.  QFileDialog::getOpenFileName(pParent, "Open some file", QString(), tr("All files (*.*)"), nullptr, QFileDialog::ReadOnly);
  11.  
  12.  // using this "non-static" version doesn't work, too
  13.  //QFileDialog FileDialog;
  14.  //FileDialog.getOpenFileName(pParent, "Open some file", QString(), tr("All files (*.*)"), nullptr, QFileDialog::ReadOnly);
  15.  
  16.  QInputDialog::getText(pParent, "Enter a text", "Blablabla:");
  17.  
  18.  // you'll hear the message box sound, but don't see anything
  19.  QMessageBox::warning(pParent, "Test Msgbox 2", "Hi, I'm another msg box");
  20.  
  21.  // the error msg will show up, but it will stay "unusable" in the background
  22.  // also the program will execute the following file dialog at the same time without waiting
  23.  QErrorMessage ErrMsg;
  24.  ErrMsg.setModal(true);
  25.  ErrMsg.showMessage(tr("This is some sort of error message"));
  26.  ErrMsg.exec();
  27.  
  28.  // this pops up too early
  29.  QFileDialog::getOpenFileName(pParent, "Open another file", QString(), tr("All files (*.*)"), nullptr, QFileDialog::ReadOnly);
  30.  
  31.  cout << "doMain() done. Time to quit()." << endl;
  32.  qApp->quit();
  33. }//end method

The problem is, if “getOpenFileName()” is called (no matter whether from an QFileDialog object or as static method), then the following message boxes don’t show up — you do hear the message box sound though. The QInputDialog (in this case, getText, but tested for other methods, too) doesn’t show either. The QErrorMessage shows, but stays in the background and is unusable. The 2nd QFileDialog does surprisingly work.

I tried many things. The slot “doMain()” belongs to a QWidget, but I also tried it with a QObject (I’d prefer the latter). I tried to pass “this” (i.e. the QWidget) as parent-pointer, but I also tried passing NULL. It all doesn’t make a difference.

I upgraded to Qt 4.7.3. I’m using VS2008 32bit. The problem occurs on both Windows 7 and Windows XP SP3 (32bit each).

I posted something similar before, but this is the the most “common” version of the problem I could derive. Old thread was http://developer.qt.nokia.com/forums/viewthread/6896 .

PLEASE help me, or try to reproduce the problem on your machine. Is my event loop messed up? I simply cannot understand what’s happening.

Here’s a zip-file with a qmake Pro-File and a Visual Studio solution: https://gigamove.rz.rwth-aachen.de/download/id/CbLuQWMNeobPuB (direct download link should be https://gigamove.rz.rwth-aachen.de/d/id/CbLuQWMNeobPuB/dd/100 )

Many thanks for any comment! Linus

 Signature 

Using Qt 4.7.3 and OpenCV 2.2 on Windows XP/7 32bit with VS 2008

26 replies

June 22, 2011

loladiro loladiro
Lab Rat
596 posts

Works perfectly on Ubuntu.
EDIT: Just downloaded your sources, same problem as you have. I’ll investigate.

June 22, 2011

loladiro loladiro
Lab Rat
596 posts

The problem doesn’t occur when QTimer isn’t used. Weird!!

June 22, 2011

LinusA LinusA
Lab Rat
62 posts

Thanks for testing!

As a work-around, could you tell me how I could invoke “doMain()” without the QTimer? Basically I want the event-loop to be running so I can display static input dialogs and execute some sequential procedure (like, in this case, doMain). I.e., what did you do avoid using QTimer?

 Signature 

Using Qt 4.7.3 and OpenCV 2.2 on Windows XP/7 32bit with VS 2008

June 22, 2011

loladiro loladiro
Lab Rat
596 posts

  1.  // call doMain of the main QObject or QWidget
  2.         myMain->doMain();

Why do you need the event loop to run?

EDIT: Another result: It doesn’t matter where the filedialog is!
EDIT2: This is a workaround:

  1.         QFileDialog *FileDialog = new QFileDialog(pParent,"Open some file", QString(), tr("All files (*.*)"));
  2.         FileDialog->exec();
  3.         delete FileDialog;

EDIT3: This workd, too BTW:
  1.        QFileDialog d(pParent,"Open some file", QString(), tr("All files (*.*)"));
  2.         d.exec();

EDIT4: I guess that means the problem lies in the code that executes platform-specific dialog. Looking through the sources now…

June 22, 2011

LinusA LinusA
Lab Rat
62 posts

loladiro wrote:

Why do you need the event loop to run?

At least I think I need it to run. Basically to have dialogs I occasionally pop up working. I don’t really remember right now, but in my huge project I’ve always been using this main() routine and CMain class as boiler-plate code. IIRC then in the beginning I only needed QErrorMessage to work, but now I sometimes have a QGLWidget which needs to react on key-presses.

Maybe you’re right, and I don’t need the event-loop, I’m a bit confused. But after all, isn’t that what you do with an QApplication? I always thought that without the app.exec(), you couldn’t use dialogs/GUI elements at all…

Anyway, thanks very much for the workarounds, I’ll try and gladly use them!

 Signature 

Using Qt 4.7.3 and OpenCV 2.2 on Windows XP/7 32bit with VS 2008

June 22, 2011

Gerolf Gerolf
Area 51 Engineer
3210 posts

You need the event loop for non nmodal windows / dialogs. Modal dialogs spin an own event loop.

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

June 22, 2011

loladiro loladiro
Lab Rat
596 posts

Ok, the problem is definitely in the platform specific file dialog if you use:

  1. QFileDialog::getOpenFileName(pParent, "Open some file", QString(), tr("All files (*.*)"), nullptr, QFileDialog::ReadOnly | QFileDialog::DontUseNativeDialog);

There’s no problem either. The only thing that’s weird about that is that it occurs on both Linux and Windows.

EDIT: This is getting more and more confusing!!!! If the main windows is visible there’s no problem!

June 22, 2011

Gerolf Gerolf
Area 51 Engineer
3210 posts

The problem is, that you give a modal window a parent window, which was never shown. If you call mainWnd.show() before, everything works fine.

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

June 22, 2011

loladiro loladiro
Lab Rat
596 posts

[deleted original post myself because of stupid question ;]
It does work. SO yeah problem solved.

June 24, 2011

LinusA LinusA
Lab Rat
62 posts

loladiro wrote:

EDIT3: This workd, too BTW:
  1.        QFileDialog d(pParent,"Open some file", QString(), tr("All files (*.*)"));
  2.         d.exec();


While this does in fact work, it shows a different looking file dialog — it feels “non-native”. I’d like to show the platform-specific default thing, in this case the default Windows version.

loladiro wrote:

EDIT4: I guess that means the problem lies in the code that executes platform-specific dialog. Looking through the sources now…

Yes, that’s what I suspect now, too.

Especially, if you change the workaround to this,

  1.        QFileDialog d(pParent,"Open some file", QString(), tr("All files (*.*)"));
  2.         //d.exec();
  3.         d.getOpenFileName();

then it’s broken again right away.

I get the feeling getOpenFileName() breaks something, or indeed I do something unallowed with my event loop, which I don’t understand…

 Signature 

Using Qt 4.7.3 and OpenCV 2.2 on Windows XP/7 32bit with VS 2008

June 24, 2011

LinusA LinusA
Lab Rat
62 posts
Gerolf wrote:
The problem is, that you give a modal window a parent window, which was never shown. If you call mainWnd.show() before, everything works fine.

Well no, I don’t give a parent window. Ideally, I’d like to pass nothing (NULL). Just during debugging, I introduced pParent and tried setting it to “this”, as well as “nullptr”. It doesn’t make a difference.

My favourite case would be just to use an QObject, which I can’t pass as parent anyway. I only tried deriving QMainWidget from QWidget, so that I could try passing “this” as parent for a test.

If you could explain what exactly I should do without a main window, than I’ll gladly try this.

loladiro wrote:

It does work. SO yeah problem solved.

Could you elaborate? Did you find something new? In my eyes, the problem is still not solved I’m afraid :-(. I’d like to somehow use “getOpenFileName()” while my event loop is running, and I still don’t get how to show message boxes afterwards.

So I could either refrain from starting my QApplication’s event loop (which I don’t want), or I could just not use getOpenFileName(). That can’t be it, right? I hope there’s just something wrong I’m doing with my “concept”…?

 Signature 

Using Qt 4.7.3 and OpenCV 2.2 on Windows XP/7 32bit with VS 2008

June 24, 2011

loladiro loladiro
Lab Rat
596 posts

You’re right it is a little odd that it only happens with native file dialogs.
The problem (at least the trivial one is that) the following code in QEventLoop is executed (q->threadData->quitNow is set) after using native file dialogs. I ‘m trying to find out why (just out of interest):
qeventloop.cpp:178,179

  1.     if (d->threadData->quitNow)
  2.         return -1;

June 24, 2011

Gerolf Gerolf
Area 51 Engineer
3210 posts

For what do you need an event loop in your example?
You want to open fife modal dialogs, one after each other, no event loop is needed for that.
You need an event loop for mode less dialogs, mode less windows or if you have a system of objects, that react on signal/slot in a not synchronous way (no queued connection, no threads)

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

June 24, 2011

loladiro loladiro
Lab Rat
596 posts

For what do you need an event loop in your example?
You want to open fife modal dialogs, one after each other, no event loop is needed for that.
You need an event loop for mode less dialogs, mode less windows or if you have a system of objects, that react on signal/slot in a not synchronous way (no queued connection, no threads)

I agree with Gerolf, however, I’m still interested in why it’s happening and will report here if I find anything. In the meantime, just use a workaround.

EDIT: I found out why the problem doesn’t occur with a visible window. Consider the following code from QApplication:

  1. void QApplicationPrivate::emitLastWindowClosed()
  2. {
  3.     if (qApp && qApp->d_func()->in_exec) {
  4.         if (QApplicationPrivate::quitOnLastWindowClosed) {
  5.             // get ready to quit, this event might be removed if the
  6.             // event loop is re-entered, however
  7.             QApplication::postEvent(qApp, new QEvent(QEvent::Quit));
  8.         }
  9.         emit qApp->lastWindowClosed();
  10.     }
  11. }

EDIT2: This also doesn’t happen if native dialog aren’t used (The event loop gets reentered immidiately, but native widgets don’t use the Qt event loop, so the application has enough time to process the quit event – it is actually done explicitly in the function that calls the native widgets – very interesting).

June 24, 2011

Gerolf Gerolf
Area 51 Engineer
3210 posts

Hi,

I tried with no message loop, and it worked as expected:

  1. void mydoMain() {
  2.         // check that the message box is working as expected!
  3.         QMessageBox::information(0, "Test Msgbox", QObject::tr("Qt Version: %1").arg(QT_VERSION_STR));
  4.  
  5.         QFileDialog::getOpenFileName(0, "Open some file", QString(), QObject::tr("All files (*.*)"), nullptr, QFileDialog::ReadOnly);
  6.  
  7.         QInputDialog::getText(0, "Enter a text", "Blablabla:");
  8.  
  9.         // you'll hear the message box sound, but don't see anything
  10.         QMessageBox::warning(0, "Test Msgbox 2", "Hi, I'm another msg box");
  11.  
  12.         // the error msg will show up, but it will stay "unusable" in the background
  13.         // also the program will execute the following file dialog at the same time without waiting
  14.         QErrorMessage ErrMsg;
  15.         ErrMsg.setModal(true);
  16.         ErrMsg.showMessage(QObject::tr("This is some sort of error message"));
  17.         ErrMsg.exec();
  18.  
  19.         // this pops up too early
  20.         QFileDialog::getOpenFileName(0, "Open another file", QString(), QObject::tr("All files (*.*)"), nullptr, QFileDialog::ReadOnly);
  21.  
  22.         cout << "doMain() done. Time to quit()." << endl;
  23. }//end method
  24.  
  25. int main(int argc, char *argv[]) {
  26.  QApplication app(argc, argv);
  27.  
  28.         mydoMain();
  29.         return 0;
  30. }//end main

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

Page  
1

  ‹‹ [SOLVED] [Class Inheritance] Need tips on creating a hierarchic class structure      [SOLVED] QTcpSocket successfully connects, but not to my server. What is it connecting to? ››

You must log in to post a reply. Not a member yet? Register here!