使用 Qt Creator 中设计的自定义小部件将页面动态添加到 QStackedWidget

Posted

技术标签:

【中文标题】使用 Qt Creator 中设计的自定义小部件将页面动态添加到 QStackedWidget【英文标题】:Dynamically adding pages to QStackedWidget using a custom widget designed in Qt Creator 【发布时间】:2017-12-05 00:37:48 【问题描述】:

所以我又迷路了。我有一个带有空 QStackedWidget 的 QMainWindow。我想使用我在 Qt Creator 中创建的自定义小部件动态填充 QStackedWidget。我尝试在另一个线程中关注Creating a custom widget in PyQT5,但这并没有真正涵盖在这种情况下从 UI 文件导入。我一直收到:

AttributeError: 'QStackedWidget' 对象没有属性 'addItemWidget'

这是 Widget 的代码...

# ItemWidget.py

from PyQt5 import uic
from PyQt5.QtWidgets import QWidget


class Widget:

    def __init__(self):
        self.text = None
        self.data = None


class ItemWidget(QWidget):

    def __init_(self, parent = None):
        self.WidgetList = []
        QWidget.__init__(self, parent = parent)
        uic.loadUi(r'interface/ItemWidget.ui', self)

    def addItemWidget(self, index, text):
        widget = Widget()
        widget.text = text
        self.WidgetList.append([])
        self.WidgetList[index].append(widget)

        # TESTING
        print(self.WidgetList)

main.py 中的相关代码:

from ItemWidget import *

for key, value in self.ItemIndexList.items():
    self.ItemStackedWidget.addItemWidget(value, key)

我知道我收到此错误是因为 QStackedWidget 没有定义名为“addItemWidget”的属性,但我不知道我需要做什么才能使其按预期工作。当我尝试使用“addWidget”覆盖该方法时,我收到了一个意外的值错误。

有什么想法吗?我对 Python 还很陌生,还在学习,所以如果我遗漏了一些重要信息,请告诉我。

我的 MainWindow.ui 有几个不同的版本。一个只有一个 QStackedWidget,我希望页面可以放在哪里,另一个完全展示了我想象的最终产品的外观。 ItemWidget.ui 文件只包含我要添加到每个 QStackedWidget 页面的元素。我还没有将它们中的任何一个提升为自定义类,我怀疑我需要这样做。

我目前正在使用 Python 3.6 和 PyQt5

** 编辑以添加 MVCE **

TestApp.py

from PyQt5.QtWidgets import QApplication
import TestMain
import sys


class MCVE(QApplication):

    def __init__(self):
        args = sys.argv
        QApplication.__init__(self, args)
        self.application = TestMain.TestMainWindow()

    def initApp(self):
        self.application.show()


if __name__ == '__main__':
    app = MCVE()
    app.initApp()
    sys.exit(app.exec_())

TestMain.py

from PyQt5.Qt import Qt
from PyQt5.QtWidgets import QMainWindow
from TestItemWidget import *


class TestMainWindow(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self, None, Qt.Window)
        uic.loadUi(r'interface/TestMainWindow.ui', self)

        SlotList = ('Header1', 0),('Header2', 1)

        for key, value in SlotList:
            self.ItemStackedWidget.addItemWidget(value, key)

TestItemWidget.py

from PyQt5 import uic
from PyQt5.QtWidgets import QWidget


class Widget:

    def __init__(self):
        self.text = None
        self.data = None


class ItemWidget(QWidget):

    def __init_(self, parent = None):
        self.WidgetList = []
        QWidget.__init__(self, parent = parent, flags = None)
        uic.loadUi(r'interface/TestItemWidget.ui', self)

    def addItemWidget(self, index, text):
        widget = Widget()
        widget.text = text
        self.WidgetList.append([])
        self.WidgetList[index].append(widget)
        print(self.WidgetList)

if __name__ == '__main__':
    pass

TestItemWidget.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item alignment="Qt::AlignHCenter">
    <widget class="QLabel" name="label">
     <property name="text">
      <string>ItemWidget</string>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

TestMainWindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>417</width>
    <height>288</height>
   </rect>
  </property>
  <property name="MainWindowUI" stdset="0">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="widget">
   <layout class="QVBoxLayout">
    <item>
     <widget class="QStackedWidget" name="ItemStackedWidget"/>
    </item>
   </layout>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

【问题讨论】:

显示你的 ItemWidget.ui 你是如何定义 ItemStackedWidget 的? 我想要一个可以重现您的错误的代码,在您的情况下,我需要您显示 ItemWidget.ui 并放置适当的 main.py 代码,我们需要一个 minimal reproducible example,也就是说,复制后可以执行的代码我不想猜测代码。 为了理解我用来帮助的动态:首先我尝试获取一个可以执行的代码,然后我尝试重现你的错误,当我得到它时,我调试你的代码并检查什么错误是。但是如果你没有显示正确的代码我会猜,我不知道你的代码,我不知道你为什么在谈论 QML,我不明白你为什么在谈论 mainwindow.ui @eyllanesc 已更新。如果我遗漏了什么,请告诉我。 【参考方案1】:

如果你想与一个小部件进行交互,你必须在小部件存在的地方进行交互,在你的情况下 QStackedWidget 存在于 TestMain.py 中,所以你必须将它与你的 addWidget 方法一起使用,它没有 addItemWidget 方法,我也推荐验证您的语法,例如 init 方法在每侧放置 2 个下划线,但在您的代码 ItemWidget 右侧只有一个:__init_,总之您的代码应如下所示,将文本添加到标签使其可见:

TestMain.py

from PyQt5.Qt import Qt
from PyQt5.QtWidgets import QMainWindow, QMenu, QToolBar, QTreeWidgetItem
from TestItemWidget import *

class TestMainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self, None, Qt.Window)
        uic.loadUi(r'interface/TestMainWindow.ui', self)

        SlotList = ('Header1', 0),('Header2', 1)

        for key, value in SlotList:
            w = ItemWidget(self)
            w.label.setText(key)
            self.ItemStackedWidget.insertWidget(value, w)

TestItemWidget.py

from PyQt5 import uic
from PyQt5.QtWidgets import QWidget

class ItemWidget(QWidget):
    def __init__(self, parent = None):
        QWidget.__init__(self, parent = parent)
        uic.loadUi(r'interface/TestItemWidget.ui', self)

【讨论】:

谢谢!您的示例有效,并且应该完全符合我的需要。为简单起见,将 ItemWidget 类放在 TestMainWindow 下会更好吗?如果我这样做了,那么在该实例中创建诸如 addItemWidget 之类的方法是否有效?我只是想多了解一点 ItemWidget 不能有 addItemWidget 方法。 注明。对于 1000 个问题,我很抱歉,我只是想了解我正在使用的源代码的原始作者是如何实现这一点的。我还有很多东西要学。 如果我看到您向我展示的代码时没有记录代码,则无法理解它是如何工作的。如果他们给了我一份类似的工作(有时他们给了我一份类似的工作),我不会接受它,或者我会接受它,条件是项目会从头开始,因为它累了,无聊和成本时间分析告诉我认为从头开始重建一个混乱的项目会更便宜。 这实际上就是我正在做的事情(从头开始)哈哈。我给你看的 repo 是原始的,我正在尝试解决这个问题,但正如你所说.. 它是一团糟。

以上是关于使用 Qt Creator 中设计的自定义小部件将页面动态添加到 QStackedWidget的主要内容,如果未能解决你的问题,请参考以下文章

在 Qt Creator Designer 中用自定义模板小部件替换小部件

如何在 Qt Creator 的主窗口中添加自定义小部件

使用 qt-creator 将库项目链接到 qt 控制台/小部件项目

QtDesigner 中的自定义 qt 小部件

QT Creator:如何为自定义小部件生成库和测试可执行文件

Qt:QScrollArea 中的自定义小部件