PySide2:不退出APP就无法关闭QMessageBox
PySide2 : cannot close a QMessageBox without quitting the APP
这是一段小代码,其中我有一个连接到 ftp 服务器并显示消息框的线程。
我不明白为什么 msgBoxWait
对话框一关闭,应用程序就崩溃了(在 FTP 线程之前终止)。
我猜这是因为它是最后显示的 window,但是,添加 QEventLoop 并不能解决问题。
你能帮帮我吗?
# coding: utf-8
import sys
import random
from PySide2 import QtCore, QtWidgets, QtGui
class Logic():
def __init__(self):
self.msgBoxWait = QtWidgets.QMessageBox()
self.ftpThread = FtpThread()
self.isConnected = False
self.loop = QtCore.QEventLoop()
def run(self):
self.ftpThread.sigIsConnected.connect(self.ftpConnected, QtCore.Qt.QueuedConnection)
self.ftpThread.finished.connect(self.ftpFinished, QtCore.Qt.QueuedConnection)
self.ftpThread.sigError.connect(self.ftpError, QtCore.Qt.QueuedConnection)
self.ftpThread.start()
QtCore.QTimer.singleShot(200, self.showWaitMsgBox)
self.loop.exec_()
def showWaitMsgBox(self):
self.msgBoxWait.setWindowTitle("Waiting")
self.msgBoxWait.setText("""Waiting for ftp connection""")
if not self.isConnected:
self.msgBoxWait.exec()
def ftpConnected(self):
print("connected")
self.isConnected = True
self.msgBoxWait.close() # <- crash here or when I click on the close button
def ftpFinished(self):
print("finished")
self.ftpThread = None
self.loop.quit()
def ftpError(self, title, message):
QtWidgets.QMessageBox.critical(None, title, message)
class FtpThread(QtCore.QThread):
sigIsConnected = QtCore.Signal()
sigError = QtCore.Signal(str, str)
def run(self):
QtCore.QThread.sleep(2)
self.sigIsConnected.emit()
QtCore.QThread.sleep(1)
self.sigError.emit("error", "An error appened")
QtCore.QThread.sleep(3)
if __name__ == "__main__":
app = QtWidgets.QApplication([])
logic = Logic()
QtCore.QTimer.singleShot(0, logic.run)
sys.exit(app.exec_())
默认情况下,Qt 配置为如果最后一个 window 关闭,应用程序将结束,因为这通常是预期的行为,但您的情况并非如此,因为有时您需要继续运行即使没有打开windows。解决方案是将 quitOnLastWindowClosed
属性 设置为 False:
# coding: utf-8
import sys
import random
from PySide2 import QtCore, QtWidgets, QtGui
class Logic:
def __init__(self):
self.msgBoxWait = QtWidgets.QMessageBox()
self.ftpThread = FtpThread()
self.isConnected = False
def run(self):
self.ftpThread.sigIsConnected.connect(
self.ftpConnected, QtCore.Qt.QueuedConnection
)
self.ftpThread.finished.connect(self.ftpFinished, QtCore.Qt.QueuedConnection)
self.ftpThread.sigError.connect(self.ftpError, QtCore.Qt.QueuedConnection)
self.ftpThread.start()
QtCore.QTimer.singleShot(200, self.showWaitMsgBox)
def showWaitMsgBox(self):
self.msgBoxWait.setWindowTitle("Waiting")
self.msgBoxWait.setText("""Waiting for ftp connection""")
if not self.isConnected:
self.msgBoxWait.exec()
def ftpConnected(self):
print("connected")
self.isConnected = True
self.msgBoxWait.close()
def ftpFinished(self):
print("finished")
self.ftpThread = None
<b># QtCore.QCoreApplication.quit() should be used
# to close the entire application if necessary
QtCore.QCoreApplication.quit()</b>
def ftpError(self, title, message):
QtWidgets.QMessageBox.critical(None, title, message)
class FtpThread(QtCore.QThread):
sigIsConnected = QtCore.Signal()
sigError = QtCore.Signal(str, str)
def run(self):
QtCore.QThread.sleep(2)
self.sigIsConnected.emit()
QtCore.QThread.sleep(1)
self.sigError.emit("error", "An error appened")
QtCore.QThread.sleep(3)
if __name__ == "__main__":
app = QtWidgets.QApplication([])
<b>app.setQuitOnLastWindowClosed(False)</b>
logic = Logic()
QtCore.QTimer.singleShot(0, logic.run)
sys.exit(app.exec_())
这是一段小代码,其中我有一个连接到 ftp 服务器并显示消息框的线程。
我不明白为什么 msgBoxWait
对话框一关闭,应用程序就崩溃了(在 FTP 线程之前终止)。
我猜这是因为它是最后显示的 window,但是,添加 QEventLoop 并不能解决问题。 你能帮帮我吗?
# coding: utf-8
import sys
import random
from PySide2 import QtCore, QtWidgets, QtGui
class Logic():
def __init__(self):
self.msgBoxWait = QtWidgets.QMessageBox()
self.ftpThread = FtpThread()
self.isConnected = False
self.loop = QtCore.QEventLoop()
def run(self):
self.ftpThread.sigIsConnected.connect(self.ftpConnected, QtCore.Qt.QueuedConnection)
self.ftpThread.finished.connect(self.ftpFinished, QtCore.Qt.QueuedConnection)
self.ftpThread.sigError.connect(self.ftpError, QtCore.Qt.QueuedConnection)
self.ftpThread.start()
QtCore.QTimer.singleShot(200, self.showWaitMsgBox)
self.loop.exec_()
def showWaitMsgBox(self):
self.msgBoxWait.setWindowTitle("Waiting")
self.msgBoxWait.setText("""Waiting for ftp connection""")
if not self.isConnected:
self.msgBoxWait.exec()
def ftpConnected(self):
print("connected")
self.isConnected = True
self.msgBoxWait.close() # <- crash here or when I click on the close button
def ftpFinished(self):
print("finished")
self.ftpThread = None
self.loop.quit()
def ftpError(self, title, message):
QtWidgets.QMessageBox.critical(None, title, message)
class FtpThread(QtCore.QThread):
sigIsConnected = QtCore.Signal()
sigError = QtCore.Signal(str, str)
def run(self):
QtCore.QThread.sleep(2)
self.sigIsConnected.emit()
QtCore.QThread.sleep(1)
self.sigError.emit("error", "An error appened")
QtCore.QThread.sleep(3)
if __name__ == "__main__":
app = QtWidgets.QApplication([])
logic = Logic()
QtCore.QTimer.singleShot(0, logic.run)
sys.exit(app.exec_())
默认情况下,Qt 配置为如果最后一个 window 关闭,应用程序将结束,因为这通常是预期的行为,但您的情况并非如此,因为有时您需要继续运行即使没有打开windows。解决方案是将 quitOnLastWindowClosed
属性 设置为 False:
# coding: utf-8
import sys
import random
from PySide2 import QtCore, QtWidgets, QtGui
class Logic:
def __init__(self):
self.msgBoxWait = QtWidgets.QMessageBox()
self.ftpThread = FtpThread()
self.isConnected = False
def run(self):
self.ftpThread.sigIsConnected.connect(
self.ftpConnected, QtCore.Qt.QueuedConnection
)
self.ftpThread.finished.connect(self.ftpFinished, QtCore.Qt.QueuedConnection)
self.ftpThread.sigError.connect(self.ftpError, QtCore.Qt.QueuedConnection)
self.ftpThread.start()
QtCore.QTimer.singleShot(200, self.showWaitMsgBox)
def showWaitMsgBox(self):
self.msgBoxWait.setWindowTitle("Waiting")
self.msgBoxWait.setText("""Waiting for ftp connection""")
if not self.isConnected:
self.msgBoxWait.exec()
def ftpConnected(self):
print("connected")
self.isConnected = True
self.msgBoxWait.close()
def ftpFinished(self):
print("finished")
self.ftpThread = None
<b># QtCore.QCoreApplication.quit() should be used
# to close the entire application if necessary
QtCore.QCoreApplication.quit()</b>
def ftpError(self, title, message):
QtWidgets.QMessageBox.critical(None, title, message)
class FtpThread(QtCore.QThread):
sigIsConnected = QtCore.Signal()
sigError = QtCore.Signal(str, str)
def run(self):
QtCore.QThread.sleep(2)
self.sigIsConnected.emit()
QtCore.QThread.sleep(1)
self.sigError.emit("error", "An error appened")
QtCore.QThread.sleep(3)
if __name__ == "__main__":
app = QtWidgets.QApplication([])
<b>app.setQuitOnLastWindowClosed(False)</b>
logic = Logic()
QtCore.QTimer.singleShot(0, logic.run)
sys.exit(app.exec_())