Python 退出/退出 PyQt 程序的正确方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38283705/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Proper way to quit/exit a PyQt program
提问by Dkellygb
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:
我有一个脚本,它有一个登录屏幕,如果按下取消按钮,我想完全退出应用程序。我尝试了 3 种方法:
- sys.exit()
- QApplication.quit()
- QCoreApplication.instance().quit()
- 系统退出()
- QApplication.quit()
- 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:
只有 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_())
采纳答案by ekhumoro
Calling QCoreApplication.quit()
is the same as calling QCoreApplication.exit(0)
. To quote from the qt docs:
调用QCoreApplication.quit()
与调用相同QCoreApplication.exit(0)
。引用qt 文档:
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]
调用此函数后,应用程序离开主事件循环并从对 exec() 的调用返回。exec() 函数返回returnCode。如果事件循环没有运行,这个函数什么都不做。[强调]
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).
所以quit()
还是exit()
什么都不像sys.exit()
。后者将终止程序,但前者只会终止事件循环(如果它正在运行)。
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.
当用户取消登录对话框时,您的示例应该只是调用sys.exit()
以终止程序。否则,您的程序将卡在阻塞的 while 循环中。
回答by Peter Wang
Instead of using QApplication.quit()
, since you defined app = QApplication(sys.argv)
, you could just write app.quit()
, and that should work!
而不是使用QApplication.quit()
,因为你定义了app = QApplication(sys.argv)
,你可以只写app.quit()
,这应该可以工作!
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.
一些不相关但可能会有所帮助的内容:我认为如果您将登录检查放在类__init__
功能的开头会更容易Ci_Co
。这样,您将从头Ci_Co
开始,但它会首先生成Login
类。如果登录失败,可以调用app.quit()
,如果成功,会自动过渡到Ci_Co
. 这使您无需在if __name__ == "__main__"
子句中写很多东西。如果您还有任何问题,请发表评论,我有一个带有登录对话框的类似项目。