Search code examples
pythonpyqtpysideqcheckboxqframe

PySide / PyQt: How to create custom classes?


I'm trying to create checkbox, frame, and grid layout objects and store them in their own list.

The output from Qt Designer looks like: enter image description here

Essentially, I want to create Checkbox1, then create a frame and grid layout to store Checkbox2 and Checkbox3.

My approach was to first create an empty list to store the objects I'm creating: checkboxList = [] Then to append it with a call to create the appropriate object checkboxList.append(CreateCheckBox(self.frame_main, self.gridLayout_main, 0, 'Checkbox 1') (for example)

This produces the output: enter image description here

The frame I created isn't visible! I'm guessing there are a few possible reasons for this:

  1. I'm creating the classes incorrectly
  2. I'm storing the objects I created incorrectly (i.e. init doesn't return anything so I'm not actually storing anything?)
  3. I'm not adding my objects to the main frame properly so they're not showing up

Why isn't my class implementation working like the code from Qt Designer and what/how do I make the changes to get a similar output?

The code imported from Qt Designer looks like this:

from PySide import QtCore, QtGui

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(494, 210)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.frame_main = QtGui.QFrame(self.centralwidget)
        self.frame_main.setGeometry(QtCore.QRect(20, 10, 435, 141))
        self.frame_main.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame_main.setFrameShadow(QtGui.QFrame.Raised)
        self.frame_main.setObjectName("frame_main")
        self.gridLayout_2 = QtGui.QGridLayout(self.frame_main)
        self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_2.setSpacing(0)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.gridLayout_main = QtGui.QGridLayout()
        self.gridLayout_main.setSpacing(0)
        self.gridLayout_main.setObjectName("gridLayout_main")
        self.frame2 = QtGui.QFrame(self.frame_main)
        self.frame2.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame2.setFrameShadow(QtGui.QFrame.Raised)
        self.frame2.setObjectName("frame2")
        self.gridLayout_16 = QtGui.QGridLayout(self.frame2)
        self.gridLayout_16.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_16.setObjectName("gridLayout_16")
        self.gridLayout2 = QtGui.QGridLayout()
        self.gridLayout2.setObjectName("gridLayout2")
        spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
        self.gridLayout2.addItem(spacerItem, 0, 0, 1, 1)
        self.checkBox2 = QtGui.QCheckBox(self.frame2)
        self.checkBox2.setObjectName("checkBox2")
        self.gridLayout2.addWidget(self.checkBox2, 0, 1, 1, 1)
        self.checkBox3 = QtGui.QCheckBox(self.frame2)
        self.checkBox3.setObjectName("checkBox3")
        self.gridLayout2.addWidget(self.checkBox3, 1, 1, 1, 1)
        self.gridLayout_16.addLayout(self.gridLayout2, 0, 0, 1, 1)
        self.gridLayout_main.addWidget(self.frame2, 1, 1, 1, 1)
        self.checkBox1 = QtGui.QCheckBox(self.frame_main)
        self.checkBox1.setObjectName("checkBox1")
        self.gridLayout_main.addWidget(self.checkBox1, 0, 1, 1, 1)
        spacerItem1 = QtGui.QSpacerItem(50, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
        self.gridLayout_main.addItem(spacerItem1, 0, 0, 1, 1)
        self.gridLayout_2.addLayout(self.gridLayout_main, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 494, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
        self.checkBox2.setText(QtGui.QApplication.translate("MainWindow", "Checkbox2", None, QtGui.QApplication.UnicodeUTF8))
        self.checkBox3.setText(QtGui.QApplication.translate("MainWindow", "Checkbox3", None, QtGui.QApplication.UnicodeUTF8))
        self.checkBox1.setText(QtGui.QApplication.translate("MainWindow", "Checkbox1", None, QtGui.QApplication.UnicodeUTF8))


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MainWindow = QtGui.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

And my code with classes looks like:

from PySide import QtCore, QtGui


class CreateCheckBox(QtGui.QCheckBox):
    def __init__(self, frame, grid, gridLoc, name, parent=None):
        #QtGui.QCheckBox.__init__(self, parent=parent)  Is this the same as the super below?
        super(CreateCheckBox, self).__init__(parent)
        self.checkbox = QtGui.QCheckBox(frame)
        grid.addWidget(self.checkbox, gridLoc, 2, 1, 1)
        self.checkbox.setText(name)


class CreateFrame(QtGui.QFrame):
    def __init__(self, parentFrame, parentGridLayout, gridLoc, parent=None):
        #QtGui.QFrame.__init__(self, parent=parent)  Is this the same as the super below?
        super(CreateFrame, self).__init__(parent)
        self.frame = QtGui.QFrame(parentFrame)
        self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtGui.QFrame.Raised)
        parentGridLayout.addWidget(self.frame, gridLoc, 2, 1, 1)


class CreateGridLayout(QtGui.QGridLayout):
    def __init__(self, parentFrame, parent=None):
        super(CreateGridLayout, self).__init__(parent)
        #QtGui.QGridLayout.__init__(self)  # This line throws an error if I include parent=parent, why?..
        self.gridLayoutSecondary = QtGui.QGridLayout(parentFrame)
        self.gridLayoutSecondary.setContentsMargins(0, 0, 0, 0)
        self.gridLayoutPrimary = QtGui.QGridLayout()
        spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
        self.gridLayoutPrimary.addItem(spacerItem, 0, 0, 1, 1)
        self.gridLayoutSecondary.addLayout(self.gridLayoutPrimary, 0, 0, 1, 1)


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(494, 210)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.frame_main = QtGui.QFrame(self.centralwidget)
        self.frame_main.setGeometry(QtCore.QRect(20, 10, 435, 141))
        self.frame_main.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame_main.setFrameShadow(QtGui.QFrame.Raised)
        self.frame_main.setObjectName("frame_main")
        self.gridLayout_main = QtGui.QGridLayout()
        self.gridLayout_main.setSpacing(0)
        self.gridLayout_main.setObjectName("gridLayout_main")
        spacerItem1 = QtGui.QSpacerItem(50, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
        self.gridLayout_main.addItem(spacerItem1, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 494, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        # List that contains new checkboxes
        checkboxList = []
        # List that contains new frames
        frameList = []
        # List than contains grid layouts for new frames
        gridLayoutList = []

        # Create 'checkBox1'
        checkboxList.append(CreateCheckBox(self.frame_main, self.gridLayout_main, 0, 'Checkbox 1'))
        # Create 'frame2'
        frameList.append(CreateFrame(self.frame_main, self.gridLayout_main, 1))
        # Create 'gridLayout2'
        gridLayoutList.append(CreateGridLayout(frameList[0]))
        # Create 'checkBox2'
        checkboxList.append(CreateCheckBox(frameList[0], gridLayoutList[0], 0, 'Checkbox 2'))
        # Create 'checkBox3'
        checkboxList.append(CreateCheckBox(frameList[0], gridLayoutList[0], 1, 'Checkbox 3'))

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MainWindow = QtGui.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Solution

  • El problema se soluciona maquetando correctamente tu aplicación, en la siguiente imagen se muestra el maquetado de QMainWindow, la imagen muestra que QMainWindow varias secciones.

    enter image description here

    In your case you should design the centralwidget,

    enter image description here

    Then, the answer can be implemented, observing that it is not necessary to use QGridLayout since it is used to distribute it as a matrix. I have created the addCheckbox function that adds the widget and stores it in the list.

    from PyQt4 import QtGui, QtCore
    
    
    class MainWindow(QtGui.QMainWindow):
        def __init__(self, parent=None):
            QtGui.QMainWindow.__init__(self, parent=parent)
    
            # add menubar
            self.menubar = QtGui.QMenuBar(self)
            self.menubar.setGeometry(QtCore.QRect(0, 0, 494, 21))
            self.setMenuBar(self.menubar)
            # add statusbar
            self.statusbar = QtGui.QStatusBar(self)
            self.setStatusBar(self.statusbar)
    
            # set central widget
            self.centralwidget = QtGui.QWidget(self)
            self.setCentralWidget(self.centralwidget)
    
            lay = QtGui.QVBoxLayout(self.centralwidget)
            self.checkBox = QtGui.QCheckBox("checkbox1", self)
            lay.addWidget(self.checkBox)
    
            self.frame = QtGui.QFrame(self)
            lay.addWidget(self.frame)
    
            self.layout_of_frame = QtGui.QVBoxLayout(self.frame)
    
            self.checkBoxList = []
            self.addCheckbox("checkbox2")
            self.addCheckbox("checkbox3")
            self.addCheckbox("checkbox4")
            self.addCheckbox("checkbox5")
    
        def addCheckbox(self, text):
            checkbox = QtGui.QCheckBox(text, self)
            self.layout_of_frame.addWidget(checkbox)
            self.checkBoxList.append(checkbox)
    

    Screenshot:

    enter image description here