在 pyqt 设计器中创建的对象上的 findChild

Posted

技术标签:

【中文标题】在 pyqt 设计器中创建的对象上的 findChild【英文标题】:findChild on object created within pyqt designer 【发布时间】:2017-11-06 15:38:51 【问题描述】:

我的 pyqt 有以下问题:

假设我在 Qt Designer 中创建了一个对象并将其保存为 .ui 文件。然后我使用 pyuic 将其转换为 .py 文件。因为我想将新模块集成到给定程序中,所以这是最喜欢的方式(因为稍后 .ui 文件将在启动时自动转换为 .py 文件)。

如果我查看我的 .py 文件,我会在窗口中看到以下内容:

class Ui_SubWindow(object):
    def setupUi(self, SubWindow):
        SubWindow.setObjectName(_fromUtf8("SubWindow"))
        ....

我有一个 RemoteWindow 类作为 MainWindow,其中启动了 SubWindow

class RemoteWindow(QtGui.QMainWindow):
  def __init__(self, subcore):
    super(RemoteWindow, self).__init__(subcore.core.gui)
    self.subcore = subcore
    self.ui = Ui_SubWindow()

现在我有一个核心程序:

class SubCore(object):
  def __init__(self, core, identity, number):
    ...
    self.gui = RemoteWindow(self)
    self.newController = NewController(self.gui)

以及新的控制器类:

class NewController(object):
  def __init__(self, subwindow):
    self.subwindow = subwindow
    self.ui = subwindow.ui

从我的控制器我想在那个窗口上调用一个 .findChild()

submitFrame = self.ui.findChild(QtGui.QFrame, "frameSubmit")

,但我得到的只是一个:

AttributeError: 'Ui_SubWindow' object has no attribute 'findChild'

我假设是这样,因为 Ui_SubWindow 类不是某个 QObject 的子类,而是一个对象的子类,对吗?

self.uisubwindow.ui 相同,其中subwindowRemoteWindow 的一个实例,它的.ui 参数是Ui_SubWindow 类。

是否有机会让 pyuic 或 Qt 设计器使这个 SubWindow 成为 QObject 的子窗口,无需操作自动生成的 .py 文件?

【问题讨论】:

【参考方案1】:

您根本不需要使用findChild,因为pyuic 会自动在ui 对象中为Qt Designer 中定义的所有小部件创建属性。属性名称取自objectName。所以你只需要:

submitFrame = self.ui.frameSubmit

【讨论】:

我想使用 findChild,因为我稍后会动态添加项目(使用 for 循环,所以 1 到 n 个对象,可通过名称“element_”+ str(i) 识别,并希望通过对象访问它们名称 @fighter-ii。您的问题专门询问在 Qt Designer 中创建的小部件。为此,我给出的解决方案是迄今为止最好的。它适用于所有对象,而不仅仅是QObject的子类;它不要求对象有父对象;即使他们确实有父母,也没有必要知道父母是什么。这就是为什么 pyuic 被设计成按照它的方式工作的原因。对于动态生成的小部件,最好使用列表:即self.ui.element[i]findChild 方法有其用处,但它不是一个好的通用解决方案。 感谢您的意见。事实上,我只是在动态生成的输入周围包裹了一个框架(并且还在 Qt 设计器中添加了这个框架),所以现在我可以访问/删除整个框架,并且可以在需要时手动构建它。【参考方案2】:

Qt Designer 创建一个设计,即一个用于填充主小部件的类,因此内部小部件不是该类的子级,如果要使用 findChild 必须对返回该类的小部件进行调用 setupUi 方法。

class RemoteWindow(QtGui.QMainWindow):
  def __init__(self, subcore):
    super(RemoteWindow, self).__init__(subcore.core.gui)
    self.subcore = subcore
    self.ui = Ui_SubWindow()
    self.ui.setupUi(self) # Here the widget is filled
    [...]

然后你应该按照以下方式使用它:

class NewController(object):
  def __init__(self, subwindow):
    self.subwindow = subwindow
    submitFrame = self.subwindow.findChild(QtGui.QFrame, "frameSubmit")
    [...]

【讨论】:

我选择你的答案作为接受的答案,因为在 self.subwindow 而不是 self.ui 上调用 findChild 就可以了。谢谢!【参考方案3】:

我最近不得不做同样的事情并将其留在这里,以防有人看到此链接与其他相关链接。 https://***.com/a/62340205/1621381

for name, obj in dict(self.__dict__).items():
        # print(str(name) + str(obj))
        obj_type = str(obj).strip("<PyQt5").rsplit(" ")[0].replace(".", '', 1)
        # obj_type = str(obj).strip("<").rsplit(" ")[0]
        # print(obj_type)
        # obj_type = obj_str.strip("<PyQt5").rsplit(" ")[0].replace(".", '', 1)
        label_name = "self." + str(name)
        try:
            label_name = self.findChild(eval(obj_type), name)
            print(str(label_name) + ' created')
        except:
            pass
        if not isinstance(obj_type, QObject):
            continue

【讨论】:

以上是关于在 pyqt 设计器中创建的对象上的 findChild的主要内容,如果未能解决你的问题,请参考以下文章

如何限制在 VS 设计器中创建的编辑框中的数字

如何在 PyQT5 中创建导航栏

ReportMachine报表设计器

Spring MVC 中创建的模型对象到底在哪里?

PyQt5 - 具有相同对象的选项卡

在 PyQT5 窗口中嵌入 VTK 对象