【问题标题】:Proper way to quit/exit a PyQt program退出/退出 PyQt 程序的正确方法
【发布时间】:2016-11-12 00:41:43
【问题描述】:

我有一个带有登录屏幕的脚本,如果按下取消按钮,我想完全退出应用程序。我尝试了 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_())

【问题讨论】:

    标签: python pyqt pyqt5


    【解决方案1】:

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

    调用此函数后,应用程序离开主 事件循环并从对 exec() 的调用中返回。 exec() 函数 返回 returnCode如果事件循环没有运行,这个函数 什么都不做。 [强调]

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

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

    【讨论】:

      【解决方案2】:

      不要使用QApplication.quit(),因为你定义了app = QApplication(sys.argv),你可以写app.quit(),这样应该可以!

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

      【讨论】:

      • 您使用 app.quit() 是绝对正确的。但是,它在 Windows 10 上的对话框上给了我同样的冻结。我在 Linux Mint 上运行该程序,它冻结了 GUI,但我能够登录到终端并发现 CPU 处于 100%,所以它似乎处于某种循环中。所以,app..quit() 的行为没有任何不同。
      • 我看到了你的第二点,下次重构时会考虑。
      • sys.exit() 呢?
      【解决方案3】:

      我尝试这 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
      

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • 这个答案基本上已经由stackoverflow.com/a/38285497/466862 提供。在回答较老的问题时,请确保您提供一个新颖的解决方案或比现有答案更好的解释。
        猜你喜欢
        • 2011-12-22
        • 1970-01-01
        • 1970-01-01
        • 2010-09-26
        • 2012-01-03
        • 1970-01-01
        • 2012-08-13
        • 1970-01-01
        相关资源
        最近更新 更多