it-swarm.com.de

Der richtige Weg, ein PyQt-Programm zu beenden/zu beenden

Ich habe ein Skript, das über einen Anmeldebildschirm verfügt, und wenn der Abbrechen-Button gedrückt wird, möchte ich die Anwendung vollständig beenden. Ich habe drei Möglichkeiten ausprobiert:

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

Nur Nummer 1 funktioniert. Die anderen beiden machen das Dialogfeld weiß und es blinkt, dann hängt es und ich kann nicht einmal zu anderen Anwendungen wechseln. Mein Code ist unten:

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

Das Aufrufen von QCoreApplication.quit() ist das gleiche wie das Aufrufen von QCoreApplication.exit(0). So zitieren Sie aus den qt-Dokumenten :

Nachdem diese Funktion aufgerufen wurde, verlässt die Anwendung die Ereignisschleife Und kehrt vom Aufruf an exec () zurück. Die Funktion exec () Gibt returnCode zurück. Wenn die Ereignisschleife nicht läuft, macht diese Funktion Nichts . [Betonung hinzugefügt]

Also sind quit() oder exit() nichts wie sys.exit(). Letzteres beendet das Programm, aber ersteres beendet lediglich die Ereignisschleife (falls sie ausgeführt wird).

Wenn der Benutzer den Anmeldedialog abbricht, sollte Ihr Beispiel einfach sys.exit() aufrufen, um das Programm zu beenden. Andernfalls bleibt Ihr Programm in der blockierenden While-Schleife hängen.

8
ekhumoro

Anstatt QApplication.quit() zu verwenden, da Sie app = QApplication(sys.argv) definiert haben, könnten Sie einfach app.quit() schreiben, und das sollte funktionieren!

Etwas, das nicht verwandt ist, aber hilfreich sein könnte: Ich denke, es wäre einfacher, wenn Sie die Anmeldeprüfung an den Anfang der __init__-Funktion Ihrer Ci_Co-Klasse setzen. Auf diese Weise beginnen Sie Ci_Co am Anfang, aber es wird zuerst die Login-Klasse erzeugt. Wenn die Anmeldung fehlschlägt, können Sie app.quit() aufrufen. Wenn dies gelingt, wird automatisch in Ci_Co übergegangen. Dies erspart Ihnen vieles, was Sie in der if __== "__main__"-Klausel schreiben müssen. Bitte kommentieren Sie, wenn Sie weitere Fragen haben. Ich habe ein ähnliches Projekt mit einem Anmeldedialogfeld. 

1
Peter Wang