web-dev-qa-db-ja.com

PyQtプログラムを終了/終了する適切な方法

ログイン画面があるスクリプトがあり、キャンセルボタンが押された場合、アプリケーションを完全に終了します。私は3つの方法を試しました:

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

番号1のみが機能します。他の2つはダイアログボックスを白色にし、点滅してからハングし、他のアプリケーションに切り替えることさえできません。私のコードは以下の通りです:

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

QCoreApplication.quit()の呼び出しは、QCoreApplication.exit(0)の呼び出しと同じです。 qt docs から引用するには:

この関数が呼び出された後、アプリケーションはメインイベントループを終了し、exec()の呼び出しから戻ります。 exec()関数はreturnCodeを返します。 イベントループが実行されていない場合、この関数は何もしません。 [強調を追加]

したがって、quit()またはexit()sys.exit()のようなものではありません。後者はプログラムを終了しますが、前者は単にイベントループを終了します(実行中の場合)。

ユーザーがログインダイアログをキャンセルした場合、サンプルはsys.exit()を呼び出してプログラムを終了するだけです。そうしないと、プログラムはブロック中のwhileループにとどまります。

12
ekhumoro

QApplication.quit()を使用する代わりに、app = QApplication(sys.argv)を定義したので、単にapp.quit()と書くことができます。

無関係だが役に立つかもしれない:___init___クラスの_Ci_Co_関数の先頭にログインチェックを入れた方が簡単だと思います。そうすれば、最初に_Ci_Co_を開始しますが、最初にLoginクラスを生成します。ログインが失敗した場合、app.quit()を呼び出すことができ、成功した場合、自動的に_Ci_Co_に移行します。これにより、_if __name__ == "__main__"_句で記述しなければならない多くのことを省くことができます。他に質問がある場合はコメントしてください。ログインダイアログボックスのある同様のプロジェクトがあります。

3
Peter Wang