Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. PyQt 5: findChild returns None
Forum Updated to NodeBB v4.3 + New Features

PyQt 5: findChild returns None

Scheduled Pinned Locked Moved Solved Qt for Python
11 Posts 3 Posters 5.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H Hubris

    Hi all,

    I have created a tabbed window where the labels and qlineedits are created using a for loop, distinguishing between the objects by having different objectName.

    class TabWidget(QWidget):
        def __init__(self, parent):
            super(QWidget, self).__init__(parent)
    
    item_names = [
                "so",
                "dc",
                "cn",
                "co",
                "ea",
                "tn",
                "sz",
                "m1",
                "m2",
                "ad",
                "de",
                "dl",
                "sd",
                "cp",
                "sh",
            ]
    
    for itemnum in range(0, len(item_names) - 2):
                self.label = QLabel(form_labels[itemnum])
                self.qledit = QLineEdit()
                if item_names[itemnum] == "so" or item_names[itemnum] == "dc":
                    self.qledit.setEnabled(False)
                self.label.setObjectName(f"{item_names[itemnum]}_l")
                self.qledit.setObjectName(f"{item_names[itemnum]}_qle")
                self.qledit.setFixedWidth(500)
                form_layout.addRow(self.label, self.qledit)
    
    

    This TabWidget class is then called in the setupUI function of the QMainWindow:

    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.initUI()
    
        def initUI(self):
            print("Initialising UI...")
            self.tab_widget = TabWidget(self)
            print("UI initialised.")
            self.setCentralWidget(self.tab_widget)
            self.move(300, 150)
            self.setWindowTitle("TopperWorks DE Utility")
            self.show()
    

    I have omitted the layout formatting of the TabWidget as I believe that to be irrelevant to the question.
    I want to change the value of one of the qlineedits that I have created from the for loop with findChild:

    qle_by_name = self.findChild(QLineEdit, "dc_qle")
    qle_by_name.setText("Test")
    

    However, findChild returns None. The findChild usage is within the TabWidget class.

    Thanks.

    jsulmJ Offline
    jsulmJ Offline
    jsulm
    Lifetime Qt Champion
    wrote on last edited by
    #2

    @Hubris You could iterate over all children (https://doc.qt.io/qt-6/qobject.html#children) and print out their names to see whether you really have such an object.
    As far as I can see you also never set the parent on the labels and line edits.

    https://forum.qt.io/topic/113070/qt-code-of-conduct

    H 1 Reply Last reply
    1
    • H Hubris

      Hi all,

      I have created a tabbed window where the labels and qlineedits are created using a for loop, distinguishing between the objects by having different objectName.

      class TabWidget(QWidget):
          def __init__(self, parent):
              super(QWidget, self).__init__(parent)
      
      item_names = [
                  "so",
                  "dc",
                  "cn",
                  "co",
                  "ea",
                  "tn",
                  "sz",
                  "m1",
                  "m2",
                  "ad",
                  "de",
                  "dl",
                  "sd",
                  "cp",
                  "sh",
              ]
      
      for itemnum in range(0, len(item_names) - 2):
                  self.label = QLabel(form_labels[itemnum])
                  self.qledit = QLineEdit()
                  if item_names[itemnum] == "so" or item_names[itemnum] == "dc":
                      self.qledit.setEnabled(False)
                  self.label.setObjectName(f"{item_names[itemnum]}_l")
                  self.qledit.setObjectName(f"{item_names[itemnum]}_qle")
                  self.qledit.setFixedWidth(500)
                  form_layout.addRow(self.label, self.qledit)
      
      

      This TabWidget class is then called in the setupUI function of the QMainWindow:

      class MainWindow(QMainWindow):
          def __init__(self):
              super().__init__()
              self.initUI()
      
          def initUI(self):
              print("Initialising UI...")
              self.tab_widget = TabWidget(self)
              print("UI initialised.")
              self.setCentralWidget(self.tab_widget)
              self.move(300, 150)
              self.setWindowTitle("TopperWorks DE Utility")
              self.show()
      

      I have omitted the layout formatting of the TabWidget as I believe that to be irrelevant to the question.
      I want to change the value of one of the qlineedits that I have created from the for loop with findChild:

      qle_by_name = self.findChild(QLineEdit, "dc_qle")
      qle_by_name.setText("Test")
      

      However, findChild returns None. The findChild usage is within the TabWidget class.

      Thanks.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #3

      @Hubris
      In addition/follow up to @jsulm

      form_layout.addRow(self.label, self.qledit)

      As code stands form_layout is a non-existent local variable.

      Separate issue:

                  self.label = QLabel(form_labels[itemnum])
                  self.qledit = QLineEdit()
      

      You are executing these statements multiple times inside a loop. These should not be assigned to (the same) class member variables.

      H 1 Reply Last reply
      0
      • jsulmJ jsulm

        @Hubris You could iterate over all children (https://doc.qt.io/qt-6/qobject.html#children) and print out their names to see whether you really have such an object.
        As far as I can see you also never set the parent on the labels and line edits.

        H Offline
        H Offline
        Hubris
        wrote on last edited by
        #4

        @jsulm Thanks for the reply. I used self.findChildren to return the QLineEdit, QPushbutton, and QLabel children but it just returns an empty array.

        I also tried to set the parent for the objects by using self.qledit.setParent(TabWidget), however I encounter the following error:

        setParent(self, QWidget): argument 1 has unexpected type 'sip.wrappertype'
        
        1 Reply Last reply
        0
        • JonBJ JonB

          @Hubris
          In addition/follow up to @jsulm

          form_layout.addRow(self.label, self.qledit)

          As code stands form_layout is a non-existent local variable.

          Separate issue:

                      self.label = QLabel(form_labels[itemnum])
                      self.qledit = QLineEdit()
          

          You are executing these statements multiple times inside a loop. These should not be assigned to (the same) class member variables.

          H Offline
          H Offline
          Hubris
          wrote on last edited by
          #5

          @JonB Thanks for the reply.

          form_layout is declared as a QFormLayout object earlier in the code. I just omitted that section. If you'd need that information I am happy to provide the whole code.

          As for assigning to the same class member variables inside the for loop,

          I am making a form which has a lot of multiple repeating QLabels, and QLineEdits. If I do not instantiate a new label for every loop, I would just be modifying the same QLabel/QLineEdit every iteration, and the result of that is undesirable.

          Is this idea not the right approach?

          Here is the output of my code:
          1134a16e-6cc7-46e2-a7cc-26e9e6f65b64-image.png

          Each QLabel and QLineEdit has a distinct objectName.

          JonBJ 1 Reply Last reply
          0
          • H Hubris

            @JonB Thanks for the reply.

            form_layout is declared as a QFormLayout object earlier in the code. I just omitted that section. If you'd need that information I am happy to provide the whole code.

            As for assigning to the same class member variables inside the for loop,

            I am making a form which has a lot of multiple repeating QLabels, and QLineEdits. If I do not instantiate a new label for every loop, I would just be modifying the same QLabel/QLineEdit every iteration, and the result of that is undesirable.

            Is this idea not the right approach?

            Here is the output of my code:
            1134a16e-6cc7-46e2-a7cc-26e9e6f65b64-image.png

            Each QLabel and QLineEdit has a distinct objectName.

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #6

            @Hubris
            That's fine.

            The observation about your class variables is probably not relevant. They end up referencing just the final label/edit you happen to create from the loop. I doubt that is useful to you as a member variable reference.

                        label = QLabel(form_labels[itemnum])
                        qledit = QLineEdit()
                        ...
            

            Wouldn't this suffice?

            If I wanted to debug your situation I'd start with @jsulm's

            @Hubris You could iterate over all children (https://doc.qt.io/qt-6/qobject.html#children) and print out their names to see whether you really have such an object.

            You could also do a quick self.findChild(QLineEdit) to see whether it finds any line edits.

            H 1 Reply Last reply
            0
            • JonBJ JonB

              @Hubris
              That's fine.

              The observation about your class variables is probably not relevant. They end up referencing just the final label/edit you happen to create from the loop. I doubt that is useful to you as a member variable reference.

                          label = QLabel(form_labels[itemnum])
                          qledit = QLineEdit()
                          ...
              

              Wouldn't this suffice?

              If I wanted to debug your situation I'd start with @jsulm's

              @Hubris You could iterate over all children (https://doc.qt.io/qt-6/qobject.html#children) and print out their names to see whether you really have such an object.

              You could also do a quick self.findChild(QLineEdit) to see whether it finds any line edits.

              H Offline
              H Offline
              Hubris
              wrote on last edited by
              #7

              @JonB Once again thank you for the reply.

              I have done your suggestion and that indeed did suffice.

              I have considered @jsulm's reply. I used the following functions:

              ...
                      print(self.findChildren(QWidget))
                      print(self.findChildren(QLabel))
                      print(self.findChildren(QLineEdit))
                      print(self.findChildren(QPushButton))
                      print(self.findChild(QLineEdit))
              ...
              

              which returned:

              []
              []
              []
              []
              None
              
              JonBJ 1 Reply Last reply
              0
              • H Hubris

                @JonB Once again thank you for the reply.

                I have done your suggestion and that indeed did suffice.

                I have considered @jsulm's reply. I used the following functions:

                ...
                        print(self.findChildren(QWidget))
                        print(self.findChildren(QLabel))
                        print(self.findChildren(QLineEdit))
                        print(self.findChildren(QPushButton))
                        print(self.findChild(QLineEdit))
                ...
                

                which returned:

                []
                []
                []
                []
                None
                
                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #8

                @Hubris
                OK, let's go back to basics :)

                You add your widgets via form_layout.addRow(self.label, self.qledit). Can you please

                • Show what form_layout is
                • Show how it is connected to your widget hierarchy, what its parent is

                We should like to try print(form_layout.findChildren()) to verify that can find the widgets you added. If form_layout is a layout (e.g. QFormLayout) then this needs to be called on its parent widget, e.g. form_layout.parentWidget().findChildren().

                Furthermore it is not clear when you are trying these findChild/findChildren() calls. They will only work when the layout/sub-widgets you have added have actually been added onto their parent to find from. For example, if you have added them to form_layout but that has not yet been set as the layout on a widget you won't find them.

                H 1 Reply Last reply
                2
                • JonBJ JonB

                  @Hubris
                  OK, let's go back to basics :)

                  You add your widgets via form_layout.addRow(self.label, self.qledit). Can you please

                  • Show what form_layout is
                  • Show how it is connected to your widget hierarchy, what its parent is

                  We should like to try print(form_layout.findChildren()) to verify that can find the widgets you added. If form_layout is a layout (e.g. QFormLayout) then this needs to be called on its parent widget, e.g. form_layout.parentWidget().findChildren().

                  Furthermore it is not clear when you are trying these findChild/findChildren() calls. They will only work when the layout/sub-widgets you have added have actually been added onto their parent to find from. For example, if you have added them to form_layout but that has not yet been set as the layout on a widget you won't find them.

                  H Offline
                  H Offline
                  Hubris
                  wrote on last edited by
                  #9

                  @JonB Wow. You hit the nail on the head.

                  As it turned out I was using tabs in my GUI, where each tab was its own QWidget. The parent for the objects was that QWidget.

                  Many thanks. I have learned something new today. I still need to read up a bit more on Children and Parents to fully understand it.

                  1 Reply Last reply
                  1
                  • H Offline
                    H Offline
                    Hubris
                    wrote on last edited by Hubris
                    #10

                    Here is the code snippet that best explains that:

                            form_layout = QFormLayout()
                    
                            # Array of
                            form_labels = [
                                "Sales Order #",
                                "Date Created",
                                "Customer Name",
                                "Contact #",
                                "Email Address",
                                "Template Name",
                                "Size",
                                "Material 1",
                                "Material 2",
                                "Additional",
                                "Delivery",
                                "Delivery Location",
                                "Ship by Date",
                                "Completed",
                                "Shipped",
                            ]
                    
                            item_names = [
                                "so",
                                "dc",
                                "cn",
                                "co",
                                "ea",
                                "tn",
                                "sz",
                                "m1",
                                "m2",
                                "ad",
                                "de",
                                "dl",
                                "sd",
                                "cp",
                                "sh",
                            ]
                    
                            # ---------- Create new tab ----------#
                            tabs = QTabWidget()
                            new_tab = QWidget()
                    
                            for itemnum in range(0, len(item_names) - 2):
                                label = QLabel(form_labels[itemnum])
                                qledit = QLineEdit()
                                if item_names[itemnum] == "so" or item_names[itemnum] == "dc":
                                    qledit.setEnabled(False)
                                label.setText(form_labels[itemnum])
                                label.setObjectName(f"{item_names[itemnum]}_l")
                                qledit.setObjectName(f"{item_names[itemnum]}_qle")
                                # self.qledit.setParent(TabWidget)
                                qledit.setFixedWidth(500)
                                form_layout.addRow(label, qledit)
                    
                            cl_btn = QPushButton("Clear Fields")
                            ce_btn = QPushButton("Create Entry")
                            em_l = QLabel()
                    
                            btn_box = QHBoxLayout()
                            btn_box.addWidget(em_l)
                            btn_box.addWidget(ce_btn)
                            btn_box.addWidget(cl_btn)
                    
                            form_layout.addRow(btn_box)
                            new_tab.setLayout(form_layout)
                    
                            qle_by_name = new_tab.findChild(QLineEdit, "dc_qle")
                            qle_by_name.setText("Test")
                    
                    JonBJ 1 Reply Last reply
                    0
                    • H Hubris

                      Here is the code snippet that best explains that:

                              form_layout = QFormLayout()
                      
                              # Array of
                              form_labels = [
                                  "Sales Order #",
                                  "Date Created",
                                  "Customer Name",
                                  "Contact #",
                                  "Email Address",
                                  "Template Name",
                                  "Size",
                                  "Material 1",
                                  "Material 2",
                                  "Additional",
                                  "Delivery",
                                  "Delivery Location",
                                  "Ship by Date",
                                  "Completed",
                                  "Shipped",
                              ]
                      
                              item_names = [
                                  "so",
                                  "dc",
                                  "cn",
                                  "co",
                                  "ea",
                                  "tn",
                                  "sz",
                                  "m1",
                                  "m2",
                                  "ad",
                                  "de",
                                  "dl",
                                  "sd",
                                  "cp",
                                  "sh",
                              ]
                      
                              # ---------- Create new tab ----------#
                              tabs = QTabWidget()
                              new_tab = QWidget()
                      
                              for itemnum in range(0, len(item_names) - 2):
                                  label = QLabel(form_labels[itemnum])
                                  qledit = QLineEdit()
                                  if item_names[itemnum] == "so" or item_names[itemnum] == "dc":
                                      qledit.setEnabled(False)
                                  label.setText(form_labels[itemnum])
                                  label.setObjectName(f"{item_names[itemnum]}_l")
                                  qledit.setObjectName(f"{item_names[itemnum]}_qle")
                                  # self.qledit.setParent(TabWidget)
                                  qledit.setFixedWidth(500)
                                  form_layout.addRow(label, qledit)
                      
                              cl_btn = QPushButton("Clear Fields")
                              ce_btn = QPushButton("Create Entry")
                              em_l = QLabel()
                      
                              btn_box = QHBoxLayout()
                              btn_box.addWidget(em_l)
                              btn_box.addWidget(ce_btn)
                              btn_box.addWidget(cl_btn)
                      
                              form_layout.addRow(btn_box)
                              new_tab.setLayout(form_layout)
                      
                              qle_by_name = new_tab.findChild(QLineEdit, "dc_qle")
                              qle_by_name.setText("Test")
                      
                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #11

                      @Hubris said in PyQt 5: findChild returns None:

                          new_tab.setLayout(form_layout)
                      
                          qle_by_name = new_tab.findChild(QLineEdit, "dc_qle")
                      

                      Yes, this makes sense for finding the child widgets! :)

                      1 Reply Last reply
                      1

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved