如何在显示 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()