Adding a widget to a layout created from .ui file

Viewed 306

I am creating a GUI in Python using PySide2, this is my .ui file:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>main_window</class>
 <widget class="QWidget" name="main_window">
  <property name="windowModality">
   <enum>Qt::NonModal</enum>
  </property>
  <property name="enabled">
   <bool>true</bool>
  </property>
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>1000</width>
    <height>640</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Testing App</string>
  </property>
  <layout class="QVBoxLayout" name="layout">
   <item>
    <layout class="QVBoxLayout" name="other_layout">
     <item>
      <widget class="QWidget" name="panel" native="true">
       <layout class="QHBoxLayout" name="layout3">
        <item>
         <layout class="QVBoxLayout" name="layout4">
          <item>
           <layout class="QHBoxLayout" name="layout5">
            <item>
             <widget class="QLabel" name="lo">
              <property name="text">
               <string>X</string>
              </property>
              <property name="alignment">
               <set>Qt::AlignCenter</set>
              </property>
             </widget>
            </item>
            <item>
             <widget class="QLineEdit" name="resolution_x">
              <property name="sizePolicy">
               <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
                <horstretch>0</horstretch>
                <verstretch>0</verstretch>
               </sizepolicy>
              </property>
              <property name="inputMethodHints">
               <set>Qt::ImhDigitsOnly</set>
              </property>
              <property name="text">
               <string>175</string>
              </property>
             </widget>
            </item>
           </layout>
          </item>
          <item>
           <layout class="QHBoxLayout" name="layout6">
            <item>
             <widget class="QLabel" name="lo2">
              <property name="text">
               <string>Y</string>
              </property>
              <property name="alignment">
               <set>Qt::AlignCenter</set>
              </property>
             </widget>
            </item>
            <item>
             <widget class="QLineEdit" name="res2">
              <property name="sizePolicy">
               <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
                <horstretch>0</horstretch>
                <verstretch>0</verstretch>
               </sizepolicy>
              </property>
              <property name="inputMethodHints">
               <set>Qt::ImhDigitsOnly</set>
              </property>
              <property name="text">
               <string>150</string>
              </property>
             </widget>
            </item>
           </layout>
          </item>
         </layout>
        </item>
        <item>
         <layout class="QVBoxLayout" name="layout7">
          <item>
           <layout class="QHBoxLayout" name="iterations_layout">
            <item>
             <widget class="QLabel" name="iterLab">
              <property name="text">
               <string>Num Passes</string>
              </property>
              <property name="alignment">
               <set>Qt::AlignCenter</set>
              </property>
             </widget>
            </item>
            <item>
             <widget class="QLineEdit" name="itr">
              <property name="sizePolicy">
               <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
                <horstretch>0</horstretch>
                <verstretch>0</verstretch>
               </sizepolicy>
              </property>
              <property name="inputMethodHints">
               <set>Qt::ImhDigitsOnly</set>
              </property>
              <property name="text">
               <string>20</string>
              </property>
             </widget>
            </item>
           </layout>
          </item>
          <item>
           <layout class="QHBoxLayout" name="layout8">
            <item>
             <widget class="QPushButton" name="reset_button">
              <property name="sizePolicy">
               <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
                <horstretch>0</horstretch>
                <verstretch>0</verstretch>
               </sizepolicy>
              </property>
              <property name="minimumSize">
               <size>
                <width>50</width>
                <height>0</height>
               </size>
              </property>
              <property name="layoutDirection">
               <enum>Qt::LeftToRight</enum>
              </property>
              <property name="text">
               <string>Zoom</string>
              </property>
             </widget>
            </item>
           </layout>
          </item>
         </layout>
        </item>
       </layout>
      </widget>
     </item>
     <item>
      <layout class="QHBoxLayout" name="process_layout">
       <item alignment="Qt::AlignLeft">
        <widget class="QLabel" name="status">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
         <property name="minimumSize">
          <size>
           <width>120</width>
           <height>20</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>120</width>
           <height>20</height>
          </size>
         </property>
         <property name="text">
          <string/>
         </property>
         <property name="alignment">
          <set>Qt::AlignCenter</set>
         </property>
        </widget>
       </item>
       <item alignment="Qt::AlignRight">
        <widget class="QLabel" name="procLab">
         <property name="minimumSize">
          <size>
           <width>77</width>
           <height>20</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>77</width>
           <height>20</height>
          </size>
         </property>
         <property name="text">
          <string>#</string>
         </property>
        </widget>
       </item>
       <item alignment="Qt::AlignRight">
        <widget class="QLineEdit" name="processes">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
         <property name="minimumSize">
          <size>
           <width>50</width>
           <height>0</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>50</width>
           <height>2000</height>
          </size>
         </property>
         <property name="inputMethodHints">
          <set>Qt::ImhDigitsOnly</set>
         </property>
         <property name="text">
          <string>8</string>
         </property>
        </widget>
       </item>
      </layout>
     </item>
    </layout>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

I want to add a widget dynamically from my Python script to the main layout ('layout'):

app = QApplication(sys.argv)
f = MyWindow()
sys.exit(app.exec_())

class MyWindow(QWidget):
    def __init__(self):
        super(MyWindow, self).__init__(None)
        ui_file = QtCore.QFile("./myui.ui")
        ui_file.open(QtCore.QFile.ReadOnly)
        loader = QtUiTools.QUiLoader()
        self.window = loader.load(ui_file)
        ui_file.close()

        self.layout.addWidget(QLabel('Stuff'))

        self.window.show()

However, I get the following error

    self.layout.addWidget(QLabel('Stuff'))
AttributeError: 'builtin_function_or_method' object has no attribute 'addWidget'

I don't understand why self.layout doesn't have the property addWidget. I thought self.layout would have a reference to a QVBoxLayout object?

1 Answers

You have several errors:

  • The widget loaded from the .ui is not the MyWindow, on the other hand in PySide2 it is not possible to load a .ui to a widget class implemented by python (in PyQt5 if possible via uic.loadUi()) so the class should handle the widget.

  • On the other hand, do not use variable names that may conflict with the names of the methods, for example the QWidget class has a layout method so it is not recommended that you have an attribute with that name, a possible solution is to use findChild to get the layout:

import sys

from PySide2.QtCore import QObject, QFile
from PySide2.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget
from PySide2.QtUiTools import QUiLoader


class Manager(QObject):
    def __init__(self):
        super(Manager, self).__init__(None)
        ui_file = QFile("./myui.ui")
        ui_file.open(QFile.ReadOnly)
        loader = QUiLoader()
        self.window = loader.load(ui_file)
        ui_file.close()
        lay = self.window.findChild(QVBoxLayout, "layout")
        lay.addWidget(QLabel("Stuff"))

        self.window.show()


if __name__ == "__main__":

    app = QApplication(sys.argv)
    f = Manager()
    sys.exit(app.exec_())
  • Another possible solution is to change the name of the layout to for example vlayout: <layout class="QVBoxLayout" name="vlayout">
import sys

from PySide2.QtCore import QObject, QFile
from PySide2.QtWidgets import QApplication, QLabel, QWidget
from PySide2.QtUiTools import QUiLoader


class Manager(QObject):
    def __init__(self):
        super(Manager, self).__init__(None)
        ui_file = QFile("./myui.ui")
        ui_file.open(QFile.ReadOnly)
        loader = QUiLoader()
        self.window = loader.load(ui_file)
        ui_file.close()
        self.window.vlayout.addWidget(QLabel("Stuff"))

        self.window.show()


if __name__ == "__main__":

    app = QApplication(sys.argv)
    f = Manager()
    sys.exit(app.exec_())
Related