Python PyQt布局中的循环窗口小部件

Python PyQt布局中的循环窗口小部件,python,pyqt,Python,Pyqt,我的问题有点像,但不是重复的。我不是在寻找一个关于如何做到这一点的高层次战略观点,而是在试图理解最惯用和最直接的方法是什么。由于PyQt是Qt C++接口的一个非常精确的绑定,所以它在布局中呈现了一种C-WISH方式。下面是我一直在使用的一种习语: for i in range(layout.count()): item = layout.itemAt(i) if type(item) == QtGui.QLayoutItem: doSomeStuff(item.layout()

我的问题有点像,但不是重复的。我不是在寻找一个关于如何做到这一点的高层次战略观点,而是在试图理解最惯用和最直接的方法是什么。由于PyQt是Qt C++接口的一个非常精确的绑定,所以它在布局中呈现了一种C-WISH方式。下面是我一直在使用的一种习语:

for i in range(layout.count()):
  item = layout.itemAt(i)
  if type(item) == QtGui.QLayoutItem:
    doSomeStuff(item.layout())
  if type(item) == QtGui.QWidgetItem:
doSomething(item.widget())
我不是最有经验的Python高手,但这似乎有点不太和谐。我的直觉告诉我,在理想情况下,Python代码应该看起来更像:

for w in layout.widgets():
  doSomething(w)

我错了吗?我错过了一个更好的成语吗?这是在PyQt中迭代小部件的最佳方式吗?我倾向于用C++来思考,所以有时我会错过“明显”的Python语言特性,使事情变得更好。我正在做的一部分工作是递归地降序到带有布局的小部件和带有布局的小部件(等等),以便在运行时自动连接到在Designer中创建的UI。添加QTabWidgets,并处理designer中设置的动态属性,我的代码基本上可以工作,但感觉非常笨拙。

我相信您已经有了解决这个问题的最简单的解决方案。PyQt(和PySead)大多只是围绕C++ API的包装器。它们在一些领域中增加了python支持——信号/时隙,基本类型,比如QString等等。但是,大部分情况下,所有的东西都完全按照C++ API的方式运行。
当然,这不需要阻止您创建自己更具python风格的库。

您可以将小部件放入生成器中,如下所示:

items = (layout.itemAt(i) for i in range(layout.count())) 
for w in items:
   doSomething(w)
如果您经常使用该代码,则可以将该代码插入到生成器函数中:

def layout_widgets(layout):
   return (layout.itemAt(i) for i in range(layout.count()))


for w in layout_widgets(layout):
   doSomething(w)

这是一个很晚的回复,但我认为它可能对将来的参考有用。我也在寻找这个问题的答案。但我想识别小部件类型,以便能够相应地处理它们。下面是我发现的示例代码:

for widget in centralwidget.children():
    if isinstance(widget, QLineEdit):
        print "linedit: %s  - %s" %(widget.objectName(),widget.text())

    if isinstance(widget, QCheckBox):
        print "checkBox: %s  - %s" %(widget.objectName(),widget.checkState())
我希望有一天这会对某人有用。:)

只是一个评论

items = (layout.itemAt(i) for i in range(layout.count())) 
for w in items:
   doSomething(w)
我尝试了第一个答案,但发现它返回一个WidgetItem类型,所以实际上我做了一个修订:

widgets = (layout.itemAt(i).widget() for i in range(layout.count())) 
for widget in widgets:
   if isinstance(widget, QLineEdit):
        print "linedit: %s  - %s" %(widget.objectName(), widget.text())
   if isinstance(widget, QCheckBox):
        print "checkBox: %s  - %s" %(widget.objectName(), widget.checkState())

找到了一种方法,如果您可以访问WindowHandler,则只需执行以下操作即可获得所有对象的字典:

widgets = vars(self)
请注意,我使用的是QT Designer(5.12),没有完整的示例来说明我是如何添加此类小部件的。但是,下面是我的示例:

from PyQt5.QtWidgets import *
FORM_CLASS, _ = loadUiType(path.join(path.dirname('__file__'), "main.ui"))

class HMIWindowHandler(QMainWindow, FORM_CLASS):
    def __init__(self, parent=None):
        super(HMIWindowHandler, self).__init__(parent)
        QMainWindow.__init__(self)
        self.setupUi(self)

        # Prints out self to prove that it is a Window Handler.
        print(self)
        print(vars(self))

        # The vars function will return all of the items of the window handler as a dict.
        widgets = vars(self)

        # Prints the dict to prove class.
        print(type(widgets))

        # Iterates each key checks for the class type and then prints the objectsName
        for each_key, value_of_key in widgets.items():
            if (value_of_key.__class__.__name__ == 'QPushButton' or value_of_key.__class__.__name__ == 'QLabel'):
                print(value_of_key.objectName())
结果是:

<views.admin.HMIWindowHandler object at 0x0000017BAC5D9EE0>

dict_items([('centralwidget', <PyQt5.QtWidgets.QWidget object at 0x0000017BAC5D9F70>),
('windows_stacked', <PyQt5.QtWidgets.QStackedWidget object at 0x0000017BAC79A040>),
('brewing', <PyQt5.QtWidgets.QWidget object at 0x0000017BAC79A0D0>), 
('boil_image', <PyQt5.QtWidgets.QLabel object at 0x0000017BAC79A160>)])

<class 'dict'>

boil_image
mash_image

记录项目([('centralwidget',),
("窗户",),,
("酿造",,
('boil_image',)])
沸腾图像
mash_图像

我只想确保您知道可以直接从ui实例访问所有小部件。您可以在ui实例上使用dir()枚举ui中的所有对象(但这也提供了类似于cruft的类和eq,但很容易过滤掉)。