我使用的是Python 2.7和PyQT4。
我想隐藏一个模态QDialog实例,然后再显示它。但是,当调用dialog.setVisible(false)时(例如,使用QTimer),dialog.exec_()调用将返回(带有QDialog.Rejected返回值)。
但是,根据http://pyqt.sourceforge.net/Docs/PyQt4/qdialog.html#exec,_exec()调用应该阻塞,直到用户关闭对话框。
有没有办法在没有_exec()返回的情况下隐藏对话框?
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
from PyQt4 import QtGui, QtCore
class MyDialog(QtGui.QDialog):
def __init__(self, parent):
QtGui.QDialog.__init__(self, parent)
def closeEvent(self, QCloseEvent):
print "Close Event"
def hideEvent(self, QHideEvent):
print "Hide Event"
class MyWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setWindowTitle("Main Window")
button = QtGui.QPushButton("Press me", self)
button.clicked.connect(self.run_dialog)
def run_dialog(self):
self.dialog = MyDialog(self)
self.dialog.setModal(True)
self.dialog.show()
QtCore.QTimer.singleShot(1000, self.hide_dialog)
status = self.dialog.exec_()
print "Dialog exited with status {}".format(status), "::", QtGui.QDialog.Accepted, QtGui.QDialog.Rejected
def hide_dialog(self):
self.dialog.setVisible(False)
# self.dialog.setHidden(True)
if __name__ == '__main__':
app = QtGui.QApplication([])
w = MyWindow()
w.show()
sys.exit(app.exec_())
PS1:此代码打印以下输出:
Hide Event
Dialog exited with status 0 :: 1 0
(未调用close事件)。
PS2:对于上下文,我试图实现一个SystemTrayIcon,它允许隐藏和恢复QMainWindow(这部分很好),可能还有它的模态QDialog而不关闭对话框。
谢谢!
答案 0 :(得分:3)
您可以通过调用基类方法来绕过QDialog.setVisible
(隐式关闭对话框)的正常行为:
def hide_dialog(self):
# self.dialog.setVisible(False)
QtGui.QWidget.setVisible(self.dialog, False)
但是,最好连接到对话框的finished()
信号,而不是使用exec()
,并明确reject()
closeEvent
中的对话框。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
from PyQt4 import QtGui, QtCore
class MyDialog(QtGui.QDialog):
def __init__(self, parent):
QtGui.QDialog.__init__(self, parent)
layout = QtGui.QHBoxLayout(self)
for title, slot in ('Ok', self.accept), ('Cancel', self.reject):
button = QtGui.QPushButton(title)
button.clicked.connect(slot)
layout.addWidget(button)
def closeEvent(self, QCloseEvent):
print "Close Event"
self.reject()
def hideEvent(self, QHideEvent):
print "Hide Event"
class MyWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setWindowTitle("Main Window")
button = QtGui.QPushButton("Press me", self)
button.clicked.connect(self.run_dialog)
def run_dialog(self):
self.dialog = MyDialog(self)
self.dialog.finished.connect(self.dialog_finished)
self.dialog.setModal(True)
self.dialog.show()
QtCore.QTimer.singleShot(3000, self.dialog.hide)
def dialog_finished(self, status):
print "Dialog exited with status:", status
if __name__ == '__main__':
app = QtGui.QApplication([])
w = MyWindow()
w.show()
sys.exit(app.exec_())
答案 1 :(得分:0)
如果有人感兴趣,以下代码为我提供了一个快速而又肮脏的方法来解决问题,尽管它并没有真正回答这个问题。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Extension of the QDialog class so that exec_() does not exit when hidden.
Dialogs inheriting will only exit exec_() via close(), reject() or accept()
"""
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class HideableQDialog(QDialog):
def __init__(self, *args, **kwargs):
super(HideableQDialog, self).__init__(*args, **kwargs)
self._mutex = QMutex()
self._is_finished = False
self._finished_condition = QWaitCondition()
self.finished.connect(self._finish_dialog)
def _finish_dialog(self):
self._is_finished = True
self._finished_condition.wakeOne()
def close(self):
super(HideableQDialog, self).close()
self._finish_dialog()
def reject(self):
super(HideableQDialog, self).reject()
self._finish_dialog()
def accept(self):
super(HideableQDialog, self).accept()
self._finish_dialog()
def exec_(self):
status = super(HideableQDialog, self).exec_()
self._mutex.lock()
condition_succedeed = False
while not condition_succedeed and not self._is_finished:
condition_succedeed = self._finished_condition.wait(self._mutex, 10)
QApplication.processEvents()
self._mutex.unlock()