Python Forum
[PyQt] QScrollArea with a gridlayout
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyQt] QScrollArea with a gridlayout
#1
I have a form that grows in height as the user provides information. Currently this occurs by dynamically adding tables and other widgets to a grid layout as the user enters information. The simplified starting point is something like this:

class UI(QtGui.QDialog):

    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent)
        self.setObjectName(_fromUtf8("Form"))
        self.resize(800, 600)
        self.gridLayout = QtGui.QGridLayout()
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self.setLayout(self.gridLayout)
Eventually, enough widgets may be added to the grid layout so the dialog content exceeds its height. Given this, I would like to implement the grid layout within the scroll area, but I can't seem to get things quite right:

class UI(QtGui.QDialog):
    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent)        

    def setupUi(self):
        self.setObjectName(_fromUtf8("Form"))
        screen = QtGui.QDesktopWidget().screenGeometry()
        self.resize(800, screen.height())
        self.gridLayout = QtGui.QGridLayout()
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))

        w = QtGui.QWidget()
        # w.setLayout(self.gridLayout)

        s = QtGui.QScrollArea()
        s.setMinimumHeight(screen.height())
        s.setWidget(w)
        s.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        s.setLayout(self.gridLayout)

        l = QtGui.QVBoxLayout()
        l.setContentsMargins(0, 0, 0, 0)
        l.setSpacing(0)
        l.addWidget(s)

        # self.setLayout(self.gridLayout)
        self.setLayout(l)
Where am I going wrong? I have a scroll area and a scroll bar, but the contents that get added don't seem to be within the scrollable area? Any guidance is greatly appreciated.
Reply
#2
From QtCreator output, this is how widgets should be added to a scroll area:

        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
        self.scrollArea.setWidgetResizable(True)
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 379, 207))
        self.verticalLayout = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents)
        self.tableWidget = QtWidgets.QTableWidget(self.scrollAreaWidgetContents)

        self.verticalLayout.addWidget(self.tableWidget)
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.gridLayout.addWidget(self.scrollArea, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
It would help if you could provide a working example of what you are trying to do.
Reply
#3
Here is a more complete example. As you select combo options, and add sections. The scrollbar does not appear, and after adding enough elements they become unusable.

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("Form"))
        Form.resize(800, 600)
        Form.setWindowTitle(_fromUtf8(""))
        self.gridLayout = QtGui.QGridLayout(Form)
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self.horizontalLayout_2 = QtGui.QHBoxLayout()
        self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
        self.btnAddSection = QtGui.QPushButton(Form)
        self.btnAddSection.setMinimumSize(QtCore.QSize(0, 30))
        self.btnAddSection.setMaximumSize(QtCore.QSize(140, 30))
        self.btnAddSection.setObjectName(_fromUtf8("btnAddSection"))
        self.btnAddSection.clicked.connect(self.add_section_button_clicked)
        self.horizontalLayout_2.addWidget(self.btnAddSection)
        self.btnApply = QtGui.QPushButton(Form)
        self.btnApply.setMinimumSize(QtCore.QSize(0, 30))
        self.btnApply.setObjectName(_fromUtf8("btnApply"))
        self.horizontalLayout_2.addWidget(self.btnApply)
        self.gridLayout.addLayout(self.horizontalLayout_2, 1, 0, 1, 1)
        self.verticalLayout = QtGui.QVBoxLayout()
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.horizontalLayout = QtGui.QHBoxLayout()
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.lblTitle = QtGui.QLabel(Form)
        self.lblTitle.setMinimumSize(QtCore.QSize(0, 30))
        self.lblTitle.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop)
        self.lblTitle.setObjectName(_fromUtf8("lblTitle"))
        self.horizontalLayout.addWidget(self.lblTitle)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.verticalLayout_2 = QtGui.QVBoxLayout()
        self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
        self.scrollArea = QtGui.QScrollArea(Form)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName(_fromUtf8("scrollArea"))
        self.scrollAreaWidgetContents_2 = QtGui.QWidget()
        self.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 776, 500))
        self.scrollAreaWidgetContents_2.setObjectName(_fromUtf8("scrollAreaWidgetContents_2"))
        self.formLayoutWidget = QtGui.QWidget(self.scrollAreaWidgetContents_2)
        self.formLayoutWidget.setGeometry(QtCore.QRect(0, 0, 761, 521))
        self.formLayoutWidget.setObjectName(_fromUtf8("formLayoutWidget"))
        self.formLayout = QtGui.QFormLayout(self.formLayoutWidget)
        self.formLayout.setVerticalSpacing(10)
        self.formLayout.setObjectName(_fromUtf8("formLayout"))

        self.scrollArea.setWidget(self.scrollAreaWidgetContents_2)
        self.verticalLayout_2.addWidget(self.scrollArea)
        self.verticalLayout.addLayout(self.verticalLayout_2)
        self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)

        self.add_section_button_clicked()
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        self.btnAddSection.setText(_translate("Form", "Add Section", None))
        self.btnApply.setText(_translate("Form", "APPLY", None))
        self.lblTitle.setText(_translate("Form", "Scrolling Test", None))
        # self.btnDeleteSection.setText(_translate("Form", "Delete Section", None))

    def add_section_button_clicked(self):
        print("add a new section")
        self.add_section_dropdown()

    def add_section_dropdown(self):
        combo = QtGui.QComboBox()
        option_list = ['Choose...', 'One', 'Two', 'Three']
        combo.addItems(option_list)
        combo.activated[str].connect(self.combo_selection_changed)
        combo.setParent(self.formLayoutWidget)
        self.formLayout.addRow(combo)

    def combo_selection_changed(self, selection):
        print(selection)
        self.add_table(selection)

    def add_table(self, selection):
        print("adding table: " + str(selection))
        tbl = QtGui.QTableWidget(3,4)
        tbl.setParent(self.formLayoutWidget)
        tbl.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        tbl.setAlternatingRowColors(True)
        tbl.setObjectName(selection)
        self.formLayout.addRow(tbl)


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    Form = QtGui.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())
Please note that this deviates from my original goal of a grid layout in a scroll area, in the sense that this approach utilizes a QVBoxLayout.

I read where it is possible to use a gridlayout, but first the layout must be put in to a qwidget.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [PyQt] QScrollArea does not work HeinKurz 3 1,368 Jan-24-2023, 09:45 PM
Last Post: HeinKurz
  [PyQt] How do I get a QScrollArea to scroll? LavaCreeperKing 9 7,811 Oct-29-2021, 08:33 AM
Last Post: Axel_Erfurt

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020