【问题标题】:How to quit Qt application before main window is displayed如何在显示主窗口之前退出 Qt 应用程序
【发布时间】:2021-01-20 01:41:18
【问题描述】:

在启动时,我的 Qt 应用程序会在显示主窗口之前显示一个带有一些选项的对话框。该对话框有一个“开始”和“取消”按钮。稍后,在显示主窗口后,当用户单击“新游戏”按钮时,会使用相同的对话框。

如果“取消”按钮是唯一显示的界面元素(即在应用程序启动时),我正在尝试让“取消”按钮退出应用程序。然而,在我当前的代码中,主窗口仍然显示。

如果我将self.view.destroy() 替换为self.view.deleteLater(),主窗口会在消失(并正常退出)之前短暂闪烁,但这不是解决方案。

如果我将view.show() 调用移动到dialog.exec_() 块内,它也不起作用。主要是因为每次在主窗口中再次显示对话框时我都会调用view.show(),但也因为即使在这种情况下,应用程序也不会真正退出。在这种情况下,主窗口不会显示,但进程会继续运行(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_()

【问题讨论】:

    标签: python pyside2


    【解决方案1】:

    如果代码分析得好,观察到“退出”在事件循环开始之前被调用,因此终止一个从未启动的事件循环是没有意义的。解决方案是在事件循环开始后立即调用 X。另一方面,quit 方法是静态的,因此不需要访问“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()
    

    【讨论】:

    • 谢谢。将 QApplication 对象传递给 App 控制器对我来说确实很奇怪。但是,当我修改代码以反映您的代码时,根本不会显示对话框。我不明白为什么。
    • @Cirrocumulus 1) 该应用程序无关紧要,因为它是样式问题。 2)我提供了一个功能代码来实现你所要求的,我不负责它的实现,因为我不知道。因此,如果您需要更多帮助,请提供minimal reproducible example,因为您不想显示的代码可能正在生成错误。
    • 你是对的,你的建议揭示了我如何绑定按钮的另一个奇怪问题。这是一个无关的问题。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    相关资源
    最近更新 更多