web-dev-qa-db-fra.com

Manière correcte de quitter/quitter un programme PyQt

J'ai un script qui a un écran de connexion et si le bouton d'annulation est enfoncé, je veux quitter l'application complètement. J'ai essayé 3 façons:

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

Seul le numéro 1 fonctionne. Les deux autres font que la boîte de dialogue est blanche et qu'elle clignote, puis se bloque et je ne peux même pas passer à d'autres applications. Mon code est ci-dessous:

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

Appeler QCoreApplication.quit() est identique à appeler QCoreApplication.exit(0). Pour citer les qt docs :

Après l’appel de cette fonction, l’application quitte le fichier principal boucle d'événement et retourne de l'appel à exec (). La fonction exec () retourne returnCode. Si la boucle d'événement n'est pas en cours d'exécution, cette fonction ne fait rien. [emphase ajoutée]

Donc quit() ou exit() ne ressemble en rien à sys.exit(). Ce dernier mettra fin au programme, mais le premier mettra simplement fin à la boucle d'événement (si elle est en cours d'exécution).

Lorsque l'utilisateur annule la boîte de dialogue de connexion, votre exemple doit simplement appeler sys.exit() pour mettre fin au programme. Sinon, votre programme restera bloqué dans la boucle en bloquant.

8
ekhumoro

Au lieu d'utiliser QApplication.quit(), puisque vous avez défini app = QApplication(sys.argv), vous pouvez simplement écrire app.quit(), et cela devrait fonctionner!

Quelque chose de différent mais qui pourrait être utile: je pense que ce serait plus facile si vous plaçiez la vérification de connexion au début de la fonction __init__ de votre classe Ci_Co. De cette façon, vous commencerez par Ci_Co au début, mais cela engendrera d'abord la classe Login. Si la connexion échoue, vous pouvez appeler app.quit(). S'il réussit, il passera automatiquement en Ci_Co. Cela vous évite beaucoup de choses que vous devez écrire dans la clause if __== "__main__". Veuillez commenter si vous avez d'autres questions, j'ai un projet similaire avec une boîte de dialogue de connexion. 

1
Peter Wang