Last active
March 8, 2018 12:06
-
-
Save martin-chatterjee/326d6fd2523a215212fb55b815fa434a to your computer and use it in GitHub Desktop.
PySide2: A QFileDialog displayed modally can not be closed by triggering accept().
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# try to import PySide2, fall back to PySide | |
try: | |
from PySide2 import QtCore, QtGui, QtWidgets | |
except ImportError: | |
from PySide import QtCore, QtGui | |
import PySide.QtGui as QtWidgets | |
import sys | |
import os | |
import tempfile | |
import shutil | |
# ----------------------------------------------------------------------------- | |
def repro(): | |
"""Creates a FileDialog and displays it modally. | |
Using a QTimer the FileDialog should automatically get closed after | |
3 seconds by triggering the slot 'accept()'. | |
This works (on Windows 10): | |
- in standalone Python 2.7 + PySide | |
- in Maya 2016 SP6 (--> PySide) | |
This does not work: (tested on Windows 10) | |
- in Maya 2017 Update4 (--> PySide2). | |
- in Maya 2018 Update2 (--> PySide2). | |
""" | |
parent_widget = _resolveParentWidget() | |
# creates a FileDialog in save mode and | |
# points it to a valid temp directory | |
temp_dir = tempfile.mkdtemp() | |
file_dialog = QtWidgets.QFileDialog(parent=parent_widget, | |
directory=temp_dir) | |
file_dialog.selectFile('saveName') | |
file_dialog.setAcceptMode(QtWidgets.QFileDialog.AcceptSave) | |
# trigger 'accept' after 3 seconds | |
def triggerAccept(): | |
file_dialog.accept() | |
# proof that QTimer is working and this got executed | |
print 'triggerAccept got called' | |
# QtCore.QTimer.singleShot(3000, file_dialog.accept) | |
QtCore.QTimer.singleShot(3000, triggerAccept) | |
print '- displaying QFileDialog modally.' | |
print '- triggering "accept()" after 3 seconds.' | |
status = file_dialog.exec_() | |
print '- return value: %s (expected: 1)' % status | |
# cleanup | |
file_dialog = None | |
shutil.rmtree(temp_dir) | |
# ----------------------------------------------------------------------------- | |
def _resolveParentWidget(): | |
"""Resolves and returns context-specific parent widget. | |
In a standalone Python context a QApplication gets created | |
and None gets returned. | |
In a Maya context the Main Maya Window gets returned. | |
""" | |
context = os.path.basename(sys.executable).lower() | |
if context.find('python') != -1: | |
app = QtWidgets.QApplication(sys.argv) | |
return None | |
elif context.find('maya') != -1: | |
for widget in QtWidgets.QApplication.topLevelWidgets(): | |
name = widget.objectName() | |
if name == 'MayaWindow': | |
return widget | |
else: | |
raise NotImplementedError('Context not supported: %s' % context) | |
if __name__ == '__main__': | |
repro() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I stumbled over this issue while writing tests for some UI code.
I want to display a QDialog modally and then automatically close it with a few seconds delay by calling accept().
This does work as expected in PySide -- however it does not work anymore in PySide2.
In PySide (both Standalone Python 2.7 and Maya 2016 SP6) I can:
1.) create a QFileDialog
2.) set up a QTimer to call accept() with a few seconds delay
3.) display it modally by calling exec_()
The expected result of this is that the QFileDialog gets displayed modally and then gets closed by the delayed call to accept().
The return value of the exec_() call will be '1' as expected.
In PySide2 (Maya 2017 & Maya 2018) this does not work...
Repro:
1.) Download the provided Gist Python file.
2.) Execute it in a PySide environment (either standalone Python 2.7 + PySide, or in the Script Editor of Maya 2016)
--> this works as expected
3.) Now execute it in a PySide2 environment (in the Script Editor of Maya 2017 or Maya 2018)
--> this does not work