简体   繁体   English

通过模态对话框关闭PyQt App

[英]Close PyQt App via a Modal Dialog

I am currently coding an application using the Qt4 python bindings that requires the user to provide login credentials. 我目前正在使用Qt4 python绑定对应用程序进行编码,该绑定要求用户提供登录凭据。 At startup of my application I show a modal dialog in which the user can enter their data. 在启动应用程序时,我显示一个模式对话框,用户可以在其中输入数据。 Since the application cannot provide useful services when the user is not logged in, I want to close the app if the user clicks the cancel button. 由于当用户未登录时应用程序无法提供有用的服务,因此如果用户单击“取消”按钮,我想关闭该应用程序。

So, if the dialog returns a negative result, I just call the close() method of my QMainWindow . 因此,如果对话框返回否定结果,则只需调用QMainWindowclose()方法。 Normally this leads to the exit of the application since there are no interactable windows any more. 通常,由于不再有可交互的窗口,因此这会导致应用程序退出。

However, if the modal Dialog has been shown before, the application simply continues to run and I have to kill it manually. 但是,如果以前显示了模式对话框,则该应用程序将继续运行,而我必须手动将其杀死。

Below is the code for an minimal example 以下是一个最小示例的代码

main.py: main.py:

import sys
from PyQt4.QtGui import QApplication
from MyMainWindow import MyMainWindow

app = QApplication(sys.argv)

window = MyMainWindow()
window.show()

app.exec_()

print "Terminated"

MyMainWindow.py: MyMainWindow.py:

from PyQt4.QtGui import QMainWindow
from PyQt4 import QtGui
from MyDialog import MyDialog

class MyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.setWindowTitle("Close App Test")

        self.centralwidget = QtGui.QWidget(self)
        self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)

        self.closeButton = QtGui.QPushButton(self.centralwidget)
        self.closeButton.setText("Close")

        self.closeButton.clicked.connect(self.exit)

    def show(self):
        QMainWindow.show(self)

        myDialog = MyDialog(self) 
        res = myDialog.exec_()  

        if res == 0:
            self.exit()
        else:
            print "Continue"

    def exit(self):
        self.close()

MyDialog.py: MyDialog.py:

from PyQt4.QtGui import QDialog
from PyQt4 import QtGui

class MyDialog(QDialog):

    def __init__(self, parent = None):
        QDialog.__init__(self, parent)

        self.setWindowTitle("Modal Dialog")

        self.resize(200, 50)

        self.closeButton = QtGui.QPushButton(self)
        self.closeButton.setText("Close")
        self.closeButton.move(10, 10)

        self.otherButton = QtGui.QPushButton(self)
        self.otherButton.setText("Do Nothing")
        self.otherButton.move(100, 10)

        self.closeButton.clicked.connect(self.reject)
        self.otherButton.clicked.connect(self.accept)

If the Close button on the modal dialog is clicked, the application continues to run even if all windows are closed. 如果单击模式对话框上的“关闭”按钮,则即使关闭了所有窗口,应用程序仍将继续运行。 If the "Do Nothing" button is clicked, and the application is closed with the close button on the main window, everything works as expected and the application terminates. 如果单击“不执行任何操作”按钮,并且使用主窗口上的“关闭”按钮关闭了应用程序,那么一切都会按预期进行,并且该应用程序将终止。

I cannot really see the difference between both cases, since each time I just call close on the main window. 我真的看不到这两种情况之间的区别,因为每次我只在主窗口上调用close时。 I can just assume that I have errors in handling the modal dialog. 我可以假设我在处理模式对话框时有错误。 I even tried tinkering around with myDialog.close() , myDialog.destroy() , as well as the quitOnClose and deleteOnClose window attributes without any positive effects. 我什至尝试修改myDialog.close()myDialog.destroy()以及quitOnClosedeleteOnClose窗口属性,而没有任何积极影响。

Any help is appreciated. 任何帮助表示赞赏。

self.exit() is called before app.exec_() if the Close button on the modal dialog is clicked, so the application continues to run. 如果单击模式对话框上的“关闭”按钮,则在app.exec_()之前调用self.exit(),因此应用程序将继续运行。 self.exit() should be called when the main event loop is running. 当主事件循环运行时,应调用self.exit()。

The following is a possible solution for the case: 以下是这种情况的可能解决方案:

from PyQt4.QtGui import QMainWindow
from PyQt4 import QtGui
from pyQt4 import QtCore

from MyDialog import MyDialog

class MyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.setWindowTitle("Close App Test")

        self.centralwidget = QtGui.QWidget(self)
        self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)

        self.closeButton = QtGui.QPushButton(self.centralwidget)
        self.closeButton.setText("Close")

        self.closeButton.clicked.connect(self.exit)

    def login(self):
        myDialog = MyDialog(self) 
        res = myDialog.exec_()  

        if res == 0:
            self.exit()
        else:
            print "Continue"

    def show(self):
        QMainWindow.show(self)
        QtCore.QTimer.singleShot(0, self.login)        

    def exit(self):
        self.close()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM