在 PyQt 主窗口中处理关闭按钮的正确方法,(红色“X”)
Posted
技术标签:
【中文标题】在 PyQt 主窗口中处理关闭按钮的正确方法,(红色“X”)【英文标题】:Proper way to handle the close button in a main window PyQt, (Red "X") 【发布时间】:2014-08-23 07:10:27 【问题描述】:首先,我是 PyQt 的新手。
我一直在尝试将一个函数链接到主窗口的关闭按钮(窗口角落的红色 x),但没有成功。现在,我的代码看起来像这样:
class Ui_MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setupUi(self)
def setupUi(self, MainWindow):
#setup code goes here
def retranslateUi(self, MainWindow):
#re translation of the GUI code
def closeEvent(self, event):
print "User has clicked the red x on the main window"
在一个单独的“主”文件中,我有以下内容:
class GUIForm(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self,parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
#self.ui.ECUStatus_txt = MyWidget.__init__.text_list
self.threadData()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = GUIForm()
myapp.show()
ret = app.exec_()
sys.exit(ret)
但是,当我通过命令提示符运行时,当我点击红色 x 时,我无法看到打印语句。我知道我是 Qt 新手,但是我看到很多人问这个问题,而且似乎没有一个答案超出上面已经写的内容。
以下答案之一: Answer #1 Answer #2
这两个解决方案都与我的相似,但仍然不起作用
尽管答案可能适用于该用户的特定代码,但我和我的 PyQt 同事对于我们的推理不起作用仍然很模糊。 PyQt 中内置的“红色 X 框”是否有定义的按钮名称?我可以像其他按钮一样将它连接到其他功能吗?
【问题讨论】:
也许aboutToQuit
信号是您正在寻找的? qt-project.org/doc/qt-5/qcoreapplication.html#aboutToQuit
可能在您的代码中您缺少到插槽的连接信号。这是 Qt 库的“主干”。
@user3419537 ,我试试看!
@NickLesnykh ,如果是这种情况,我将如何解决它?
@sudobangbang,在您的情况下,您可以将 aboutToQuit 信号(从 QApplication 实例发出)连接到处理程序,或 Qt 术语中的插槽。您可以在app
实例化之后添加:app.aboutToQuit.connect(on_exit)
【参考方案1】:
您永远不应该修改从您的 ui 文件生成的类。相反,您应该子类化并修改子类。
从您的代码的外观来看,您实际上是在创建两个QMainWindow
s,并且 closeEvent 被错误的捕获(大概是隐藏了一个?)。那就是self.ui
是一个QMainWindow
,它没有显示出来,也没有添加到GUIForm
的UI 中。相反,您自己明确地使用Ui_MainWindow.setupUi()
方法,将小部件添加到您自己的QMainWindow
, 'GUIForm`。
相反,您应该将 Ui_MainWindow
类保留为从 ui 文件生成时的状态,然后将您的主 python 文件修改为:
class GUIForm(Ui_MainWindow):
def __init__(self, parent=None):
Ui_MainWindow.__init__(self, parent)
self.threadData()
def closeEvent(self, event):
print "User has clicked the red x on the main window"
event.accept()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = GUIForm()
myapp.show()
ret = app.exec_()
sys.exit(ret)
通过这种方式,您可以扩展自动生成的 UI 文件的行为。这样可以轻松地从 .ui 文件重新生成 python 文件,而无需重新添加代码(这正是您永远不应该修改自动生成的 Python 文件的原因)
【讨论】:
我认为这个例子的问题在于它不包括任何方法来区分 X 关闭和由于操作完成而关闭的窗口 - 例如,单击 OK 按钮或其他东西。由于 closeEvent 在窗口关闭时运行并且不是唯一的。 @NL23codes 大多数人不需要区分,Qt 没有明确的方式来区分“x”按钮,因为该按钮由操作系统窗口管理器处理。但是,基于this,您可以通过查看closeEvent
方法中event.spontaneous()
的值来有效区分它。【参考方案2】:
有时,在处理来自主窗口的事件信号时会出现问题。
您可以使用代码:
app.aboutToQuit.connect(self.closeEvent)
您可以在 closeEvent 函数中编写自己的代码。
注意:
app 是 QtGui.QApplication 实例的名称
这是完整代码的演示:
from PyQt4 import QtCore, QtGui
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
#================================
app.aboutToQuit.connect(self.closeEvent)
#================================
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle('Demo')
#================================
def closeEvent(self):
#Your desired functionality here
print('Close button pressed')
import sys
sys.exit(0)
#================================
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
希望对你有帮助。
【讨论】:
aboutToQuit
信号对我来说太迟了。我想让一个弹出窗口询问用户是否要退出,但是一旦启动此信号,应用程序就已经退出,我只是得到一个问题弹出窗口,现在它对应用程序是否关闭没有影响。有什么想法吗?
'aboutToQuit' 事件调用另一个函数 closeEvent。您可以在此处放置 if-else 逻辑以检查确认。最终 'sys.exit(0)' 关闭应用程序。
我就是这样尝试的,但是 gui 在确认弹出窗口打开之前就关闭了,所以即使你选择 No
程序已经关闭了。
有没有办法绕过@Kajsa 提出的问题?
这个例子对我有用,但 closeEvent 需要两个参数,就像这样给出 (self,g)。【参考方案3】:
我遇到了同样的问题,我有一个对话框窗口提示,在继续操作之前要求用户输入。用户可以在处理操作之前添加输入,跳过添加输入并继续处理,或者使用取消按钮或单击对话框窗口的 X 取消操作。
我所做的是创建一个保存布尔值的变量,该变量将在关闭窗口之前进行检查,以便在窗口被强制关闭的情况下,很明显进程已中止。
class Ui_MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setupUi(self)
#This variable will be your way of determining how the window was closed
self.force_close = True
self.buttonOk.clicked.connect(self.someOtherFunction)
def setupUi(self, MainWindow):
#setup code goes here
def retranslateUi(self, MainWindow):
#re translation of the GUI code
def someOtherFunction(self):
# Do some things here if needed
print('All done')
# Assuming some operation is performed and a value or result is generated
# Since this function completed, there is no need to force close the window
# So it can be set to False
self.force_close = False
# the below close() is a built-in function and will automatically trigger the
# closeEvent
self.close()
def closeEvent(self, event):
if self.force_close is True:
# Here is where you could add you code to perform some operation
# due to the user clicking the X
【讨论】:
以上是关于在 PyQt 主窗口中处理关闭按钮的正确方法,(红色“X”)的主要内容,如果未能解决你的问题,请参考以下文章