如何在显示 main window 之前退出 Qt 应用程序
How to quit Qt application before main window is displayed
启动时,我的 Qt 应用程序会在显示主 window 之前显示一个包含一些选项的对话框。该对话框有一个 'Start' 和 'Cancel' 按钮。稍后会使用相同的对话框,在显示主要 window 之后,当用户单击 'New Game' 按钮时。
如果 'Cancel' 按钮是唯一显示的界面元素(即在应用程序启动时),我正在尝试让它退出应用程序。然而,在我当前的代码中,主要 window 仍然显示。
如果我将 self.view.destroy()
替换为 self.view.deleteLater()
,主要的 window 会在消失(并正确退出)之前短暂闪烁,但这不是解决方案。
如果我将 view.show()
调用移到 dialog.exec_()
块内,它也不起作用。主要是因为每次从主 window 中再次显示对话框时我都会调用 view.show()
,但也因为即使在这种情况下应用程序也不会真正退出。在这种情况下,主 window 未显示,但进程保持 运行(Python 应用程序图标在 Dock 中仍然可见)。
我在这里做错了什么?我读过 other similar questions 但我不明白如何在我的案例中应用这些解决方案。
(macOS 10.15.6 上的 PySide2 5.15.1)
class App:
def __init__(self, app, game, view):
self.app = app
self.game = game
self.view = view
# Display the dialog
# Same callback is bound to a QPushButton in MainWindow
self.cb_start_dialog()
def cb_start_dialog(self):
# Do some initialisation
dialog = DialogNewGame() # A subclass of QDialog
if dialog.exec_():
# Setup the interface
else:
if not self.view.isVisible():
# Condition evaluates correctly
# (False on app launch,
# True if main window is displayed)
self.view.destroy()
self.app.quit() # Doesn't work, main window still displayed
def main():
application = QApplication()
view = MainWindow() # A QWidget with the main window
model = Game() # Application logic
App(application, model, view)
view.show()
application.exec_()
如果代码分析得好,可以观察到在eventloop开始之前调用了“quit”,所以终止一个从未开始的eventloop是没有意义的。解决方案是在事件循环启动后立即调用 X。另一方面,退出方法是静态的,因此没有必要访问“self.app”
from PySide2.QtCore import QTimer
from PySide2.QtWidgets import QApplication, QDialog, QMainWindow
class MainWindow(QMainWindow):
pass
class DialogNewGame(QDialog):
pass
class Game:
pass
class App:
def __init__(self, game, view):
self.game = game
self.view = view
QTimer.singleShot(0, self.cb_start_dialog)
def cb_start_dialog(self):
dialog = DialogNewGame()
if dialog.exec_():
pass
else:
QApplication.quit()
def main():
application = QApplication()
view = MainWindow()
model = Game()
app = App(model, view)
view.show()
application.exec_()
if __name__ == "__main__":
main()
启动时,我的 Qt 应用程序会在显示主 window 之前显示一个包含一些选项的对话框。该对话框有一个 'Start' 和 'Cancel' 按钮。稍后会使用相同的对话框,在显示主要 window 之后,当用户单击 'New Game' 按钮时。
如果 'Cancel' 按钮是唯一显示的界面元素(即在应用程序启动时),我正在尝试让它退出应用程序。然而,在我当前的代码中,主要 window 仍然显示。
如果我将 self.view.destroy()
替换为 self.view.deleteLater()
,主要的 window 会在消失(并正确退出)之前短暂闪烁,但这不是解决方案。
如果我将 view.show()
调用移到 dialog.exec_()
块内,它也不起作用。主要是因为每次从主 window 中再次显示对话框时我都会调用 view.show()
,但也因为即使在这种情况下应用程序也不会真正退出。在这种情况下,主 window 未显示,但进程保持 运行(Python 应用程序图标在 Dock 中仍然可见)。
我在这里做错了什么?我读过 other similar questions 但我不明白如何在我的案例中应用这些解决方案。
(macOS 10.15.6 上的 PySide2 5.15.1)
class App:
def __init__(self, app, game, view):
self.app = app
self.game = game
self.view = view
# Display the dialog
# Same callback is bound to a QPushButton in MainWindow
self.cb_start_dialog()
def cb_start_dialog(self):
# Do some initialisation
dialog = DialogNewGame() # A subclass of QDialog
if dialog.exec_():
# Setup the interface
else:
if not self.view.isVisible():
# Condition evaluates correctly
# (False on app launch,
# True if main window is displayed)
self.view.destroy()
self.app.quit() # Doesn't work, main window still displayed
def main():
application = QApplication()
view = MainWindow() # A QWidget with the main window
model = Game() # Application logic
App(application, model, view)
view.show()
application.exec_()
如果代码分析得好,可以观察到在eventloop开始之前调用了“quit”,所以终止一个从未开始的eventloop是没有意义的。解决方案是在事件循环启动后立即调用 X。另一方面,退出方法是静态的,因此没有必要访问“self.app”
from PySide2.QtCore import QTimer
from PySide2.QtWidgets import QApplication, QDialog, QMainWindow
class MainWindow(QMainWindow):
pass
class DialogNewGame(QDialog):
pass
class Game:
pass
class App:
def __init__(self, game, view):
self.game = game
self.view = view
QTimer.singleShot(0, self.cb_start_dialog)
def cb_start_dialog(self):
dialog = DialogNewGame()
if dialog.exec_():
pass
else:
QApplication.quit()
def main():
application = QApplication()
view = MainWindow()
model = Game()
app = App(model, view)
view.show()
application.exec_()
if __name__ == "__main__":
main()