在PyQt布局中循环遍历小部件

时间:2011-03-01 03:29:27

标签: python pyqt

我的问题与Get a layout's widgets in PyQT有些相关,但并不重复。我没有寻找关于如何做到这一点的高层战略观点,而是试图了解最惯用和最简单的方法。由于PyQt是Qt C ++ API的一个非常精确的绑定,它提供了一种C-ish方法来获取布局中的小部件。这是我一直在使用的那种习语:

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,处理设计器中设置的动态属性,我的代码基本上可以工作,但它只是感觉非常笨重。

5 个答案:

答案 0 :(得分:14)

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

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())

我希望有一天这对某人有用。 :)

答案 1 :(得分:6)

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

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)

答案 2 :(得分:5)

只是评论,

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())

答案 3 :(得分:0)

我相信你已经有了解决这个问题的最简单方法。 PyQt(和PySide)大多只是围绕C ++ API的包装器。它们确实在一些领域增加了更多的pythonic支持 - 信号/插槽,QString等基本类型,但在大多数情况下,所有内容都与C ++ API完全一样。

当然,这并不能阻止你制作自己更多的pythonic库..

答案 4 :(得分:0)

找到了一种方法,如果您可以访问 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