1

I have been trying to create a program where QFrames are dynamically added to a QVboxLayout. As more and more frames are added to the layout, the frames not having enough space to occupy. I searched google for the problem, I found many stackoverflow answers, all of which use a QScrollArea. But when I added a QScrollArea with the QVBoxLayout in it, the scrollbars don't show up. Any help would be greatly appreciated. Here is the minimum reproducible example:

from PyQt5 import QtCore, QtGui, QtWidgets

class Frame(QtWidgets.QFrame):
    def __init__(self,parent=None):
        super(Frame,self).__init__(parent)
        self.setStyleSheet("background-color:red")
        self.lbl=QtWidgets.QLabel(self)
        self.lbl.setText("Sample Test")
        self.font=QtGui.QFont()
        self.font.setPointSize(20)
        self.lbl.setFont(self.font)
        
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        
        MainWindow.setObjectName("MainWindow")
        MainWindow.setFixedSize(984, 641)
        MainWindow.setStyleSheet("background-color:rgb(255,255,255);")
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        #Some UI

        self.addBtn = QtWidgets.QPushButton(self.centralwidget)
        self.addBtn.setGeometry(QtCore.QRect(450, 100, 71, 51))
        self.addBtn.setText("+")
        font = QtGui.QFont()
        font.setPointSize(20)
        self.addBtn.setFont(font)
        self.addBtn.setStyleSheet("background-color:rgb(89, 183, 255);border-radius:15px;color:white;")
        self.addBtn.setFlat(True)
        self.addBtn.setObjectName("addTaskBtn")
        self.addBtn.clicked.connect(self.addFrame)
        
        self.scroller = QtWidgets.QScrollArea(self.centralwidget)
        self.scroller.setGeometry(QtCore.QRect(0, 230, 991, 411))
        self.scroller.setWidgetResizable(True)
        self.scroller.setObjectName("scroller")
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 989, 409))
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.layoutManager=QtWidgets.QVBoxLayout(self.scroller)
        self.scrollAreaWidgetContents.setLayout(self.layoutManager)
        self.scroller.setWidget(self.scrollAreaWidgetContents)
        MainWindow.setCentralWidget(self.centralwidget)


    def addFrame(self):
        #Code to add the frame
        self.layoutManager.addWidget(Frame())

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

1 Answer 1

2

The problem is that when you use the widgetResizable mode in True it uses the sizeHint of the widget but in your case the sizeHint of the QFrame does not take into account that of the QLabel. One possible solution is to use a layout.

class Frame(QtWidgets.QFrame):
    def __init__(self, parent=None):
        super(Frame, self).__init__(parent)
        self.setStyleSheet("background-color:red")

        self.lbl = QtWidgets.QLabel()
        self.lbl.setText("Sample Test")

        font = QtGui.QFont()
        font.setPointSize(20)
        self.lbl.setFont(font)

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.lbl)

On the other hand I see that in my test the scrollbar appears but only a part since as you established it using setGeometry it has problems to recalculate some values. A possible solution is to use a widget that contains the QScrollArea:

# ...
self.addBtn.clicked.connect(self.addFrame)

container = QtWidgets.QWidget(self.centralwidget)
container.setGeometry(QtCore.QRect(0, 230, 991, 411))
lay_container = QtWidgets.QVBoxLayout(container)

self.scroller = QtWidgets.QScrollArea()
lay_container.addWidget(self.scroller)
self.scroller.setWidgetResizable(True)
# ...
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.