1

I am experiencing a weird behavior from this simple line of code, which I wanted to use outside a pyqt GUI class

from PyQt4 import QtGui

FilePath=QtGui.QFileDialog.getOpenFileName(None,'choose the file')

When I first implemented it, it worked (probably because I run some other code before that I cannot trace back).

Then after restarting python, it stopped working and it crashes saying:

QWidget: Must construct a QApplication before a QPaintDevice

The same exact code works fine when implemented in a GUI, where the first argument is of course self.

But I would like to use the same filedialog in an external function I use for a different purpose, outside a GUI context.

Is it possible and what could be a way/workaround to implement that ? I would like to avoid using wx, easygui or tk

Mel
  • 5,837
  • 10
  • 37
  • 42
JacoSolari
  • 1,226
  • 14
  • 28

2 Answers2

1

In order to use the Qt UI elements (such as QFileDialog), you generally have to have a QApplication running. It seems a little unorthodox, but you can get your snippet to run just by instantiating a QApplication prior to your QFileDialog, like so

from PyQt4 import QtGui
app = QtGui.QApplication([])
FilePath=QtGui.QFileDialog.getOpenFileName(None,'choose the file')

Technically, this will work, though I'm not quite sure I can endorse doing this.

JCVanHamme
  • 1,050
  • 7
  • 12
  • Thanks for your suggestion JCV, I already tried it. This solution works on itself, but as soon as I add some more code it crashes badly.. – JacoSolari Dec 15 '15 at 17:01
1

Qt applications are built around an event loop and require QApplication instance. Dialogs have their own event loop, so if all you want is a wizard (a series of dialogs that open/close in sequence), then in principle all you need is the QApplication instance. The following works in PyQt 5:

from PyQt5 import Qt
app = Qt.QApplication([])
FilePath=Qt.QFileDialog.getOpenFileName(None,'choose the file')
print(FilePath)

However, if you have other code that assumes an application event loop, all bets are off. In that case, you could do the following:

from PyQt4 import Qt
app = Qt.QApplication([])
FilePath=Qt.QFileDialog.getOpenFileName(None,'choose the file')
print(FilePath)
...create widgets....
QTimer.singleShot(someWidgetMethod)
app.exec_()

The single-shot timer will fire only during the app.exec_(), thus calling some of your code as part of the event loop.

All that being said,it is much better to create a main window and connect slots to signals and call app.exec_(). There are many examples included with PyQt, check those.

Oliver
  • 27,510
  • 9
  • 72
  • 103