June 17, 2011

LinusA LinusA
Lab Rat
64 posts

2nd QInputDialog after QFileDialog immediately closes

 

Hi,

I’m not sure whether this a bug in Qt or if I did something wrong, but I suppose it’s the latter ;).

Basically, after I’ve used a combination of QInputDialog::getItem() and QFileDialog::getOpenFileName(), any following QInputDialog::getItem() dialogs will just pop up quickly and close immediately, while QFileDialog::getOpenFileName() still works as expected. What am I doing wrong? Any clues as how to debug it will be appreciated…

Here’s my main method:

  1. int main(int argc, char *argv[]) {
  2.  QApplication app(argc, argv);
  3.  
  4.  CMain myMain(&app);
  5.  QTimer::singleShot(0, &myMain, SLOT(doMain()));
  6.  
  7.  int returnVal = app.exec();
  8.  cout << "Press ENTER to exit..." << endl;
  9.  getchar();
  10.  return returnVal;
  11. }//end main

It uses the CMain class. Header is here:

  1. class CMain : public QObject {
  2.  Q_OBJECT
  3.  
  4. public:
  5.  CMain(QObject *parent);
  6.  ~CMain();
  7.  
  8. public slots:
  9.  void doMain();
  10.  
  11. private:
  12. };//end class

And the body with the problematic bit of code here (c’tor and d’tors are empty):

  1. void CMain::doMain() {
  2.  
  3.  QStringList myItems;
  4.  myItems << "Item 1" << "Item 2" << "Item 3";
  5.  
  6.  // this all works!
  7.  QInputDialog::getItem(nullptr, "Test input 1", "Choose:", myItems);
  8.  QFileDialog::getOpenFileName(nullptr, "Open some file", QString(), tr("All files (*.*)"), nullptr, QFileDialog::ReadOnly);
  9.  
  10.  // now, this dialog will pop up ("flash") and close immediately
  11.  QInputDialog::getItem(nullptr, "Test input 2", "Choose 2nd time:", myItems);
  12.  
  13.  // this works again!
  14.  QFileDialog::getOpenFileName(nullptr, "Open another file", QString(), tr("All files (*.*)"), nullptr, QFileDialog::ReadOnly);
  15.  
  16.  cout << "doMain() done. Time to quit()." << endl;
  17.  qApp->quit();
  18.  
  19. }//end method

I’ve uploaded the whole project as Visual Studio 2008 Solution (and I exported a .pro file from it). I’m on Windows 7 32bit, and using Qt 4.7.1. Here’s the link: https://gigamove.rz.rwth-aachen.de/download/id/n25wbjrCjbGKrY

Thanks very much for looking into this! Best regards,
Linus

5 replies

June 17, 2011

jim_kaiser jim_kaiser
Lab Rat
144 posts

Could you try it by passing a parent (‘this’ in your case, instead of the nullptr)? Also, I see you have used a singleshot timer to run the doMain() function.. Could you put some time in this.. so that the slot is not executed before the app.exec() is called.. The exec() starts the event loop of the application..
Normally we show our widgets and then run app.exec() to start the event loop. Now, the application is setup to respond to user events. In your case, if you want to use a timer.

Try:

  1. QTimer::singleShot(2000, &myMain, SLOT(doMain()));

June 17, 2011

LinusA LinusA
Lab Rat
64 posts

jim_kaiser wrote:
Could you try it by passing a parent (‘this’ in your case, instead of the nullptr)?

Unfortunately, I can’t. ‘this’ is just a QObject, while the pointer needs to be a QWidget. Do I need to upgrade my CMain class to be a QWidget? I mean, I’m just calling static methods, just like message-boxes, I don’t see why I’d need a widget. And in fact, it does work right until the 2nd time.

When I debug the code, I see that the dialog’s “show()” method is called, it pops up, and closes right away.

jim_kaiser wrote:
Also, I see you have used a singleshot timer to run the doMain() function.. Could you put some time in this.. so that the slot is not executed before the app.exec() is called.. The exec() starts the event loop of the application..
Normally we show our widgets and then run app.exec() to start the event loop. Now, the application is setup to respond to user events. In your case, if you want to use a timer.

Try:
@QTimer::singleShot(2000, &myMain, SLOT));@

Thanks, I just tried it, and it makes no difference.

I think I’ve read in a book (IIRC by Mark Summerfield) that you can use the time 0, and the “singleShot” will be scheduled right away when the event loop starts — so that shouldn’t be the problem.

However, is there a way to “start” my doMain() slot without the timer? So that the event-loop is running and I get the chance to execute code sequentially, just as I do now?

June 17, 2011

jim_kaiser jim_kaiser
Lab Rat
144 posts

Hmm… you’re right.. i guess the timer would execute at the start of the event loop..

As for running the slot without a timer.. well.. why not put a button and use doMain() as the slot for clicked..

Anyways, I will try and test this issue and get back to you..

June 17, 2011

LinusA LinusA
Lab Rat
64 posts

jim_kaiser wrote:

As for running the slot without a timer.. well.. why not put a button and use doMain() as the slot for clicked..

I created this project to demonstrate my problem. In my real “big” application, it’s not clear from the start whether I need to show input dialogs at all. I check command line arguments, and if they’re present, CMain does all the processing without user interaction. But if the command line arguments are missing, the parameters are retrieved via those static file and input dialogs. So I don’t really have a main window or widget or anything. On the other hand, again: I don’t see why this would cause problems…

Thanks for discussing this, it might help me to get the insight I need

June 18, 2011

LinusA LinusA
Lab Rat
64 posts

It gets worse. I experimented, and it seems that after a call to QFileDialog::getOpenFileName(), many (built-in) dialogs are somehow broken. I confirmed this for QMessageBox and QErrorMessage. Go ahead and change the code in doMain() to this:

  1. void CMain::doMain() {
  2.  // check that the message box is working as expected!
  3.  QMessageBox::information(nullptr, "Test Msgbox", tr("Qt Version: %1").arg(QT_VERSION_STR));
  4.  
  5.  // THIS QFILEDIALOG BREAKS SOMETHING!
  6.  // comment the next line out to see everything working normal!
  7.  QFileDialog::getOpenFileName(nullptr, "Open some file", QString(), tr("All files (*.*)"), nullptr, QFileDialog::ReadOnly);
  8.  
  9.  // you'll hear the message box sound, but don't see anything
  10.  QMessageBox::warning(nullptr, "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(tr("This is some sort of error message"));
  17.  ErrMsg.exec();
  18.  
  19.  // this pops up too early
  20.  QFileDialog::getOpenFileName(nullptr, "Open another file", QString(), tr("All files (*.*)"), nullptr, QFileDialog::ReadOnly);
  21.  
  22.  cout << "doMain() done. Time to quit()." << endl;
  23.  qApp->quit();
  24. }//end method

Comment out the first QFileDialog::getOpenFileName() where the comment suggest it. You’ll see the expected behaviour. Now, enable that line, and watch every dialog (except another file dialog) “break” after that line. I’ve tested this on 2 different machines, both VS 2008, Qt 4.7.1, one Windows 7 32bit, the other WinXP SP3 32bit.

 
  ‹‹ Reading Data from CSV FILE      Align elements in QHBoxLayout ››

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