python - 如何为具有可以访问主 GUI 功能的子窗口/类的窗口创建 GUI 类?
问题描述
如何为具有可以访问主 GUI 功能的子窗口/类的窗口创建 GUI 类?
我有下面的代码,它修改了设计师编译的 .ui 代码。我想要它做的是,当单击右上角的“X”或使用 File -> Exit 函数时,关闭包含 Window_SecondWindow 类的窗口,并再次显示主窗口——有效地show()
从子类。我想一次只显示一个窗口。
当代码按原样运行时,Window_SecondWindow 类隐藏,但立即再次显示,让我相信super
正在充当self
.
from PyQt5 import QtWidgets
from GUI import compiled_MainWindow
from GUI import compiled_SecondWindow
class Window_MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.ui = compiled_MainWindow.Ui_MainWindow()
self.ui.setupUi(self)
self.ui.closeEvent = self.clicked_EXIT
# connect widgets
self.ui.Btn.clicked.connect(self.clicked_Btn)
self.ui.actionExit.triggered.connect(self.clicked_EXIT)
# add windows
self.SecondWindow = SecondWindow()
# more windows attached to main window
def clicked_Btn(self):
self.hide()
self.SecondWindow.show()
def clicked_EXIT(self):
self.close()
class Window_SecondWindow(Window_MainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.ui = compiled_SecondWindow.Ui_MainWindow()
self.ui.setupUi(self)
self.ui.closeEvent = self.clicked_EXIT
self.ui.actionExit.triggered.connect(self.clicked_EXIT)
def clicked_EXIT(self):
self.hide()
super().show()
解决方案
在回答你的问题之前,我想谈谈一些重要的方面。
首先,永远不要编辑从 pyuic 生成的代码来创建你的程序。它们旨在用作导入的模块,主要用作“资源”:您将它们导入并集成到您的代码中,但您应该始终保持它们原样。有关这方面的更多信息,请参阅有关使用 Designer的文档。
重写中的函数要小心
__init__
:有些函数不是“虚拟的”(因此,不能以这种方式覆盖),并且在某些情况下,Qt 总是调用基类函数名;如果需要,只需覆盖该方法并使用 super() 调用基类实现。此外,closeEvent
将关闭事件作为强制参数,您必须将其添加到您的覆盖函数中,即使您不使用它(在以下示例中我只是使用*args
)。也就是说,您永远不应该将重写的函数用作具有不同参数的插槽,反之亦然。最后,你不应该对属性和变量名使用大写的名字,因为它会混淆并且容易出错(大写通常只用于类名,而不是它们的实例名)。
现在,答案
你几乎是对的,super()
充当“自我”,因为它只是针对实例show()
调用类的继承方法。所以,它调用了 的 show 方法,但是由于实例是第二个窗口,所以它和做的一样,都是实例;完全一样。_Window_MainWindow
Window_MainWindow.show(self)
self
Window_SecondWindow
self.show()
有两种(半)可能性。
第一个更明显的解决方案是将主窗口实例的引用提供给第二个:
class Window_MainWindow(QtWidgets.QMainWindow):
def __init__(self):
# ...
self.secondWindow = Window_SecondWindow()
self.secondWindow.mainWindow = self
class Window_SecondWindow(Window_MainWindow):
# ...
def clicked_EXIT(self, *args):
self.hide()
self.mainWindow.show()
请注意,正如@noras 在评论中指出的那样,您可以在 init 参数中将主窗口设置为父窗口,但这仅适用于 QMainWindow 和 QDialog 后代;如果子窗口小部件是任何其他类型的,它将显示在父窗口内,而不是作为单独的窗口。
第二个(也是“Qt-wise correct”)是为第二个类创建一个在关闭时发出的信号,并将其连接到主窗口中,以便在发生这种情况时再次显示:
class Window_MainWindow(QtWidgets.QMainWindow):
def __init__(self):
# ...
self.secondWindow = Window_SecondWindow()
self.secondWindow.closed.connect(self.show)
class Window_SecondWindow(Window_MainWindow):
closed = QtCore.pyqtSignal()
def clicked_EXIT(self, *args):
self.hide()
self.closed.emit()
第二种半解决方案是使用事件过滤器:
class Window_MainWindow(QtWidgets.QMainWindow):
def __init__(self):
# ...
self.secondWindow = Window_SecondWindow()
self.secondWindow.installEventFilter(self)
def eventFilter(self, source, event):
if source == self.secondWindow and event.type() == QtCore.QEvent.Close:
self.show()
return super().eventFilter(source, event)
推荐阅读
- google-cloud-platform - 没有云存储的 Firebase 云功能
- pygame - 如何在pygame中制作圆形表面
- php - 在 laravel 中过滤关系
- cordova - 科尔多瓦 paytm 支付网关插件中的 501 错误代码
- python - 为什么我的 Python 函数没有返回任何值?
- android - 如何在 SQLite for Android 中使用关键字 AUTOINCREMENT
- oracle - 无法创建池的初始连接 - 带有 Oracle DB 的 Spring Boot
- .htaccess - 根据浏览器语言和 utm 参数重定向 .htaccess
- xml - 如何根据“sec/@disp-level”值在“sec/title”元素下生成格式化数字序列
- logstash - Kibana - 结合两列在 Kibana 中创建一个新列