简体   繁体   中英

Proper way to quit/exit a PyQt program

I have a script which has a login screen and if the cancel button is pressed, I want to exit the application altogether. I have tried 3 ways:

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

Only number 1 works. The other two makes the dialog box white and it flashes then hangs and I cannot even switch to other applications. My code is below:

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_())

Calling QCoreApplication.quit() is the same as calling QCoreApplication.exit(0) . To quote from the 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]

So quit() or exit() are nothing like sys.exit() . The latter will terminate the program, but the former will merely terminate the event-loop (if it's running).

When the user cancels the login dialog, your example should just call sys.exit() to terminate the program. Otherwise, your program will just get stuck in the blocking while-loop.

Instead of using QApplication.quit() , since you defined app = QApplication(sys.argv) , you could just write app.quit() , and that should work!

Something unrelated but might be helpful: I think it would be easier if you put the login check at the beginning of the __init__ function of your Ci_Co class. That way, you will start Ci_Co at the beginning, but it will first spawn the Login class. If the login fails, you can call app.quit() , and if it succeeds, it will automatically transition into Ci_Co . This saves you from a lot of the things you have to write in the if __name__ == "__main__" clause. Please comment if you have any more questions, I have a similar project with a login dialog box.

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

i try this 3 method to close my MainWindow() but it didn't work for my code.

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

So i use self.close() method which work Completely fine with my code.

here is my code

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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