Python 在 PyQt 主窗口中处理关闭按钮的正确方法,(红色“X”)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24532043/
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 handle the close button in a main window PyQt, (Red "X")
提问by sudobangbang
First off, I am a complete newbie to PyQt.
首先,我是 PyQt 的完全新手。
I have been trying to link a function to the Main Window's close button (the red x in the corner of the window) but I haven't been having any success. Right now, my code looks something like this:
我一直在尝试将一个函数链接到主窗口的关闭按钮(窗口角落的红色 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"
In a seperate "main" file I have the folowing:
在一个单独的“主”文件中,我有以下内容:
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)
However, when I run via command prompt, I am not able to see the print statement when I hit the red x. I know I am new to Qt, but I have seen quite a few people ask this question, and none of the answers seemed to get beyond what is already written above.
但是,当我通过命令提示符运行时,当我点击红色 x 时,我看不到打印语句。我知道我是 Qt 的新手,但我看到很多人问这个问题,而且似乎没有一个答案超出上面已经写的内容。
One of these answers: Answer #1Answer #2
Both of these solutions are similar to mine, but it still doesn't work
这两个解决方案都与我的相似,但仍然不起作用
Despite the answer, which may have worked for that user's specific code, my fellow PyQt colleagues and I are still quite foggy on the reasoning ours is not working. Is there a defined button name for the "Red X box" built into PyQt? Can I connect it to another function the someway I would for other buttons?
尽管答案可能适用于该用户的特定代码,但我和我的 PyQt 同事仍然对我们的推理不起作用感到困惑。PyQt 中内置的“Red X 框”是否有定义的按钮名称?我可以将它连接到另一个功能,就像连接其他按钮一样吗?
采纳答案by three_pineapples
You shouldn't ever modify the class that was generated from your ui file. Instead you should subclass and modify the subclass.
您不应该修改从 ui 文件生成的类。相反,您应该创建子类并修改子类。
From the looks of your code, you are actually creating two QMainWindow
s and the closeEvent is being caught for the wrong one (presumably that one is hidden?). That is self.ui
is a QMainWindow
that is not being shown, and is not added to the UI of GUIForm
. Instead you are using the Ui_MainWindow.setupUi()
method explicitly yourself, to add the widgets to your own QMainWindow
, 'GUIForm`.
从代码的外观来看,您实际上是在创建两个QMainWindow
s 并且 closeEvent 被错误的一个捕获(大概是隐藏的一个?)。即self.ui
是QMainWindow
一个没有被示出,并且不被添加到的UI GUIForm
。相反,您Ui_MainWindow.setupUi()
自己明确地使用该方法,将小部件添加到您自己的QMainWindow
“GUIForm”中。
Instead, what you should to do is leave your Ui_MainWindow
class as it was when it was generated from the ui file, and then modify your main python file to be:
相反,您应该做的是让您的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)
This way you are extending the behaviour of the auto-generated UI file. This makes it easy to regenerate the python file from the .ui file without having to re-add code (this is precisely why you should never modify the auto-generated Python file)
通过这种方式,您可以扩展自动生成的 UI 文件的行为。这使得从 .ui 文件重新生成 python 文件变得容易,而无需重新添加代码(这正是为什么你不应该修改自动生成的 Python 文件的原因)
回答by xeon
Sometimes, issues occur when handling event signals from the main window.
有时,处理来自主窗口的事件信号时会出现问题。
You can use the code :
您可以使用以下代码:
app.aboutToQuit.connect(self.closeEvent)
and you can write your own code in the closeEventfunction.
您可以在closeEvent函数中编写自己的代码。
Note :
笔记 :
appis the name of the QtGui.QApplicationinstance
app是QtGui.QApplication实例的名称
Here's a demo of the full code :
这是完整代码的演示:
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_())
Hope it helps.
希望能帮助到你。
回答by NL23codes
I ran into this same problem, where I had a dialog window prompt, asking the user for input before proceeding in an operation. The user could add input before the operation was processed, skip adding input and process anyway or cancel out of the operation using a Cancel button or by clicking the X of the dialog window.
我遇到了同样的问题,我有一个对话框窗口提示,在继续操作之前要求用户输入。用户可以在处理操作之前添加输入,无论如何都可以跳过添加输入和处理,或者使用“取消”按钮或单击对话框窗口的 X 取消操作。
What I did instead was create a variable holding a boolean value that would be checked before closing the window, so that in the event the window was forced closed, it's clear that a process was aborted.
我所做的是创建一个包含布尔值的变量,该变量将在关闭窗口之前进行检查,以便在窗口被强制关闭的情况下,很明显进程已中止。
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