Ejaz
Ejaz

Reputation: 1632

How to use findChildren?

I want to click a button and clear around 20 QLineEdits.

I am trying to use findChildren() and put all the QLineEdit in a QListWidget

self.StudentAdmissionLayout = QGridLayout()
self.StudentAdmissionLayout.addWidget(self.StudentName,1,0,1,1)

The self.StudentAdmissionLayout layout has all the QLineEdit placed on it.

self.myList = QListWidget()
self.Item = QListWidgetItem()
self.Item = self.StudentAdmissionLayout.findChildren(QLineEdit)
self.myList.addItem(self.Item)

I am getting below error:

TypeError: arguments did not match any overloaded call:
QListWidget.addItem(QListWidgetItem): argument 1 has unexpected type 'list'
QListWidget.addItem(QString): argument 1 has unexpected type 'list'

I am trying to put the above 4 lines in a loop. But the 3rd line isn't working, I am not sure how to make it work. Please suggest.

Upvotes: 6

Views: 26361

Answers (3)

Bandhit Suksiri
Bandhit Suksiri

Reputation: 3450

OK, we have to understand behavior of list-of-QObject QObject.findChildren (self, type type, QString name = QString()) . The documentation for this class says

Returns all children of this object with the given name that can be cast to type T, or an empty list if there are no such objects. Omitting the name argument causes all object names to be matched. The search is performed recursively.

Source: http://pyqt.sourceforge.net/Docs/PyQt4/qobject.html#findChildren

Then, it returns a Python list to you and each element in the list is type of T (the type you provided as input). So your problem:

TypeError: arguments did not match any overloaded call:
QListWidget.addItem(QListWidgetItem): argument 1 has unexpected type 'list'
QListWidget.addItem(QString): argument 1 has unexpected type 'list'

is because you pass a list, but addItem requires a QListWidgetItem or QString (or Python str). If you want to pass a Python list you must use a for loop to iterate over the data:

myQListWidget = QListWidget()
listsItem = ['my', 'data', 'are', 'here', '!']
for item in listsItem:
    myQListWidget.addItem(item)

Another problem I found is that your search data are QLineEdits , It isn’t a supported type in any overloaded method of QListWidget.addItem(). I think you can't pass it in to this method. But if you need the "text" in each QLineEdit only, you can convert it like this:

self.studentAdmissionQGridLayout = QGridLayout()
.
.
.
self.myQListWidget = QListWidget()
listsMyQLineEdit = self.studentAdmissionQGridLayout.findChildren(QLineEdit)
for myQLineEdit in listsMyQLineEdit:
    self.myQListWidget.addItem(myQLineEdit.text())

Here is a reference to help to understand QListWidget.addItem():

http://pyqt.sourceforge.net/Docs/PyQt4/qlistwidget.html#addItem

Upvotes: 11

Mike R
Mike R

Reputation: 879

So i ended up wanting to be able to loop through all the child objects from a uic module loaded and link them up dynamically and this loop may be of help for you with some slight mods for only the qlineedit ones

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

The full code for stub i used to be able to load Qt Designer uic file and connect up custom slots and signals and live test is below

from PyQt5 import uic, QtWidgets
import sys
from PyQt5.QtCore import QObject

qtCreatorFile = "mainwindow.ui"  # Type your file path
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)


class build(Ui_MainWindow, QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)

        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


def start():
    app = QtWidgets.QApplication(sys.argv)
    bld = build()
    bld.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    start()

Upvotes: 2

ekhumoro
ekhumoro

Reputation: 120588

If the line-edits do not have the layout as parent, findChildren will not find them.

It may be better to iterate over the layout something like this:

for row in range(layout.rowCount()):
    for column in range(layout.columnCount()):
        item = layout.itemAtPosition(row, column)
        if item is not None:
            widget = item.widget()
            if isinstance(widget, QLineEdit):
                listWidget.addItem(widget.text())

Upvotes: 4

Related Questions