[英]how to close a modal dialog in showEvent?
我不敢相信我不得不問這個問題,但我無法從showEvent
關閉 PyQt5 模態對話框。
這是一個演示該問題的微型示例程序。 該測試程序的預期行為是因為設置somethingWentTerriblyWrong
,一旦按下btnShowDialog
,模態對話框可能會出現一瞬間,即使那么長,然后自動關閉,但正如您從下面的屏幕截圖中看到的那樣不會發生。
# test.py
from PyQt5.QtWidgets import QApplication, QDialog, QWidget, QLabel, QGridLayout, QPushButton
from PyQt5.Qt import Qt
def main():
app = QApplication([])
mainForm = MainForm()
mainForm.show()
app.exec()
# end main
class MainForm(QWidget):
def __init__(self):
super().__init__()
self.initUi()
self.myDialog = MyDialog(self)
# set that something went wrong in the dialog so it should close immediately in the showEvent
self.myDialog.somethingWentTerriblyWrong = True
# end function
def initUi(self):
# set default form size and location
self.setGeometry(400, 400, 400, 275)
# declare a button
self.btnShowDialog = QPushButton('show dialog')
self.btnShowDialog.clicked.connect(self.btnShowDialogClicked)
# increase the font size
setFontSize(self.btnShowDialog, 16)
# declare a layout and add the label to the layout
self.gridLayout = QGridLayout()
self.gridLayout.addWidget(self.btnShowDialog)
# add the layout to the form
self.setLayout(self.gridLayout)
# end function
def btnShowDialogClicked(self):
retVal = self.myDialog.exec()
print('retVal = ' + str(retVal))
# end function
# end class
class MyDialog(QDialog):
def __init__(self, parent):
super().__init__(parent)
self.initUi()
self.somethingWentTerriblyWrong = False
# end function
def initUi(self):
self.setGeometry(250, 250, 250, 175)
self.lblDialog = QLabel('label on Dialog')
# center the label and increase the font size
self.lblDialog.setAlignment(Qt.AlignCenter)
setFontSize(self.lblDialog, 15)
self.gridLayout = QGridLayout()
self.gridLayout.addWidget(self.lblDialog)
self.setLayout(self.gridLayout)
# end function
def showEvent(self, event):
super(MyDialog, self).showEvent(event)
# if something went terribly wrong, close this dialog form
if self.somethingWentTerriblyWrong:
print('in if self.somethingWentTerriblyWrong:')
# self.reject()
self.close()
# end if
# end function
# end class
def setFontSize(widget, fontSize):
font = widget.font()
font.setPointSize(fontSize)
widget.setFont(font)
# end function
if __name__ == '__main__':
main()
在MyDialog
中,我希望 self.reject() 或 self.close() 行可以關閉對話框,但是在 Ubuntu 18.04 上,至少模態對話框會變暗並掛起:
我確定在MyDialog
的 show 事件中執行if
語句,因為終端 output 是:
$ python3 test.py
in if self.somethingWentTerriblyWrong:
我究竟做錯了什么?
您過早地關閉了小部件,在showEvent()
方法中小部件是可見的,但設備上的繪畫尚未完成,因此在調用close()
方法時停止繪畫,並且它沒有隱藏,因為內部標志未更新生成未定義的行為。
解決方案是使用QTimer
或QMetaObject
在showEvent()
之后的某個瞬間(留出正確更新內部標志的時間)之后立即調用close()
方法(或reject()
方法):
from PyQt5.QtCore import Qt, QTimer, QMetaObject
# ...
class MyDialog(QDialog):
# ...
def showEvent(self, event):
super(MyDialog, self).showEvent(event)
# if something went terribly wrong, close this dialog form
if self.somethingWentTerriblyWrong:
print("in if self.somethingWentTerriblyWrong:")
QTimer.singleShot(0, self.close)
# or
# - QMetaObject.invokeMethod(self, "close", Qt.QueuedConnection)
# - QTimer.singleShot(0, self.reject)
# - QMetaObject.invokeMethod(self, "reject", Qt.QueuedConnection)
根據 eyllanesc 的回答完成工作示例:
# CloseDialogInShowEvent.py
from PyQt5.QtWidgets import QApplication, QDialog, QWidget, QLabel, QGridLayout, QPushButton
from PyQt5.Qt import Qt
from PyQt5.QtCore import QTimer
def main():
app = QApplication([])
mainForm = MainForm()
mainForm.show()
app.exec()
# end main
class MainForm(QWidget):
def __init__(self):
super().__init__()
self.initUi()
self.myDialog = MyDialog(self)
# set that something went wrong in the dialog so it should close immediately in the showEvent
self.myDialog.somethingWentTerriblyWrong = True
# end function
def initUi(self):
# set default form size and location
self.setGeometry(400, 400, 400, 275)
# declare a button
self.btnShowDialog = QPushButton('show dialog')
self.btnShowDialog.clicked.connect(self.btnShowDialogClicked)
# increase the font size
setFontSize(self.btnShowDialog, 16)
# declare a layout and add the label to the layout
self.gridLayout = QGridLayout()
self.gridLayout.addWidget(self.btnShowDialog)
# add the layout to the form
self.setLayout(self.gridLayout)
# end function
def btnShowDialogClicked(self):
retVal = self.myDialog.exec()
print('retVal = ' + str(retVal))
# end function
# end class
class MyDialog(QDialog):
def __init__(self, parent):
super().__init__(parent)
self.initUi()
self.somethingWentTerriblyWrong = False
self.tmrClose = QTimer(self)
self.tmrClose.setInterval(200)
self.tmrClose.timeout.connect(self.tmrCloseTimeout)
# end function
def initUi(self):
self.setGeometry(250, 250, 250, 175)
self.lblDialog = QLabel('label on Dialog')
# center the label and increase the font size
self.lblDialog.setAlignment(Qt.AlignCenter)
setFontSize(self.lblDialog, 15)
self.gridLayout = QGridLayout()
self.gridLayout.addWidget(self.lblDialog)
self.setLayout(self.gridLayout)
# end function
def showEvent(self, event):
super(MyDialog, self).showEvent(event)
# if something went terribly wrong, close this dialog form
if self.somethingWentTerriblyWrong:
print('in if self.somethingWentTerriblyWrong:')
self.tmrClose.start()
# end if
# end function
def tmrCloseTimeout(self):
self.reject()
# end function
# end class
def setFontSize(widget, fontSize):
font = widget.font()
font.setPointSize(fontSize)
widget.setFont(font)
# end function
if __name__ == '__main__':
main()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.