quit/exit PyQt 程序的正确方法

Proper way to quit/exit a PyQt program

我有一个带有登录屏幕的脚本,如果按下取消按钮,我想完全退出该应用程序。我尝试了 3 种方法:

  1. sys.exit()
  2. QApplication.quit()
  3. QCoreApplication.instance().quit()

只有数字 1 有效。另外两个使对话框变白,然后闪烁然后挂起,我什至无法切换到其他应用程序。我的代码如下:

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtSql import *
from PyQt5.QtWidgets import *


import csv
import sys
from datetime import datetime, timedelta, time
import os

from ci_co_table import *
from login import *

class Ci_Co(QMainWindow):
    """Check in and check out module"""

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

class Login(QDialog):
    """User login """
    def __init__(self):
        QDialog.__init__(self)
        self.ui = Ui_login_form()
        self.ui.setupUi(self)
        self.ui.buttonBox.accepted.connect(lambda: self.handle_login(servers=servers))
        servers = {}
        with open('servers.csv', newline='') as csvfile:
            server_reader = csv.reader(csvfile)
            for row in server_reader:
                self.ui.cbo_db_name.addItem(row[1])
                servers[row[1]] = (row[0],row[2])

    def handle_login(self, servers=''):
        global user
        global pword
        global database
        global server
        global bg_colour
        user = self.ui.username.text()
        pword = self.ui.password.text()
        database = self.ui.cbo_db_name.currentText()
        server = servers[database][0]
        bg_colour = servers[database][1]


if __name__=="__main__":
    app=QApplication(sys.argv)
    global hotdate
    global hotdate_string
    global folio_num
    global user
    global pword
    global dbase
    global server
    pword = ""
    global database
    global bg_colour
    #Login
    while True:
        if Login().exec_() == QDialog.Accepted:
            db = QSqlDatabase.addDatabase("QPSQL");
            db.setHostName(server)
            db.setDatabaseName(database);
            db.setUserName(user);
            db.setPassword(pword)
            if (db.open()==False):     
                QMessageBox.critical(None, "Database Error", db.lastError().text())
            else:
                break
        else:
            #QApplication.quit()
            QCoreApplication.instance().quit()            
            #sys.exit()


    myapp = Ci_Co()
    myapp.show()
    sys.exit(app.exec_())

而不是使用 QApplication.quit(),因为您定义了 app = QApplication(sys.argv),您可以只写 app.quit(),这应该可以工作!

一些不相关但可能有用的东西:我认为如果将登录检查放在 Ci_Co class 的 __init__ 函数的开头会更容易。这样,您将在开头启动 Ci_Co,但它会首先生成 Login class。如果登录失败,可以调用app.quit(),如果登录成功,会自动过渡到Ci_Co。这使您免于必须在 if __name__ == "__main__" 子句中编写的许多内容。如果您还有其他问题,请发表评论,我有一个带有登录对话框的类似项目。

调用 QCoreApplication.quit() 与调用 QCoreApplication.exit(0) 相同。引用自qt docs

After this function has been called, the application leaves the main event loop and returns from the call to exec(). The exec() function returns returnCode. If the event loop is not running, this function does nothing. [emphasis added]

所以 quit()exit()sys.exit() 完全不同。后者将终止程序,但前者只会终止事件循环(如果它是 运行)。

当用户取消登录对话框时,您的示例应该只调用 sys.exit() 来终止程序。否则,您的程序将卡在阻塞的 while 循环中。

sys.exit(app.exec_()) 添加到您的代码中

我尝试了这 3 种方法来关闭我的 MainWindow() 但它对我的代码不起作用。

  1. sys.exit()
  2. QApplication.quit()
  3. qApp.quite()

所以我使用 self.close() 方法,该方法完全适用于我的代码。

这是我的代码

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
    
        self.ui.QPushButton.clicked.connect(lambda: self.shutprocess())
    
    def shutprocess(self):
        reply = QMessageBox.question(self, 'Window Close', 'Are you sure you want to close the window?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
                self.close()
            print('Window closed')
        else:
            pass