如何将PyQt中设备控制用QMainWindow作为另一个主窗口的标签页加载?
问题
我编写了一个基于PyQt的设备控制GUI脚本,GUI是继承自QMainWindow的MyApp类,通过QT Designer生成的.ui文件构建,代码如下:
qtCreatorFile = "GuiTemplate.ui" #.ui file created with QT Designer Ui_MainWindow, QtBaseClass = uic.loadUiType("GuiGuiTemplate.ui")[0] class MyApp(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self): QtWidgets.QMainWindow.__init__(self) Ui_MainWindow.__init__(self) self.setupUi(self) # 定义一堆方法和信号槽连接... if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) window = MyApp() window.show() sys.exit(app.exec_())
现在需要实现多设备控制功能,目标是每连接一台设备就新增一个标签页,标签页内容为该GUI的副本。
我尝试在新脚本中导入MyApp类并直接添加为标签页,代码如下:
from originalGuiScript import MyApp # 初始化代码 self.tabs = QTabWidget() self.tabs.addTab(MyApp,"Tab 1")
但运行时出现以下错误:
TypeError: arguments did not match any overloaded call:
addTab(self, QWidget, str): argument 1 has unexpected type 'sip.wrappertype'
addTab(self, QWidget, QIcon, str): argument 1 has unexpected type 'sip.wrappertype'
解决方法
错误核心原因:addTab要求传入QWidget的实例对象,但你传入的是MyApp类本身,而非类的实例,所以触发类型不匹配错误。
基础修复:传入类实例
先把代码改成创建MyApp的实例再传入:
from originalGuiScript import MyApp # 初始化代码 self.tabs = QTabWidget() # 创建MyApp实例,再添加为标签页 new_device_tab = MyApp() self.tabs.addTab(new_device_tab, "Tab 1")
优化方案:调整MyApp的继承类
因为MyApp原继承自QMainWindow(顶层窗口类),嵌套在标签页中会存在布局冗余(比如自带的菜单栏、工具栏容器),更合理的做法是让MyApp继承QWidget:
# originalGuiScript.py 中的修改 class MyApp(QtWidgets.QWidget, Ui_MainWindow): def __init__(self): QtWidgets.QWidget.__init__(self) Ui_MainWindow.__init__(self) self.setupUi(self) # 原有的方法和信号槽逻辑保持不变
之后按基础修复的方式创建实例添加标签页即可,这样的部件更适合作为标签页内容。
兼容方案:不修改原类的情况下调整窗口特性
如果不想改动原有MyApp类,可以在创建实例后去掉其顶层窗口特性:
from originalGuiScript import MyApp from PyQt5 import QtCore # 初始化代码 self.tabs = QTabWidget() new_device_window = MyApp() # 去掉顶层窗口的标题栏等特性,使其适配子部件场景 new_device_window.setWindowFlags(QtCore.Qt.Widget) self.tabs.addTab(new_device_window, "Tab 1")
后续每连接一台设备,重复执行创建MyApp实例并添加新标签的逻辑即可实现多设备控制。
内容的提问来源于stack exchange,提问作者FlacoTheTaco

