Reputation: 1206
I think it should be much easier to create a scrollable window in PyQt. I have a list of labels that goes out of the window and I would like to scroll down to view them. At the moment the code does not give me an error, but the window just doesn't appear:
class Example(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout()
lbl_arr = makeLabelArr()
for i in range(1,8):
qb = lbl_arr[i]
# qb.setFixedWidth(300)
layout.addWidget(qb)
layout.setAlignment(Qt.AlignTop)
scroll = QScrollArea()
scroll.setWidget(self)
scroll.setWidgetResizable(True)
scroll.setFixedHeight(400)
layout.addWidget(scroll)
self.setLayout(layout)
self.setGeometry(0, 0, 600, 220)
self.setWindowTitle('SnP watchlist')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
#print(QDesktopWidget().availableGeometry())
ex = Example()
sys.exit(app.exec_())
Upvotes: 10
Views: 20456
Reputation: 15692
This illustrates one way to do things
import sys
from PyQt5 import QtWidgets, QtCore
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.resize(600, 200)
self.setWindowTitle('One way to do scrolling')
def add_stuff():
self.add_stuff()
QtCore.QTimer.singleShot(500, add_stuff)
def add_stuff(self):
self.resize(1200, 800)
# comment out these blocks, starting with the bottom one
central_widget = QtWidgets.QFrame(self)
self.setCentralWidget(central_widget)
central_widget.setLayout(QtWidgets.QVBoxLayout(central_widget))
central_widget.setStyleSheet('border: 5px solid green;')
scroll_area = QtWidgets.QScrollArea()
scroll_area.setWidgetResizable(True)
central_widget.layout().addWidget(scroll_area)
scroll_area.setStyleSheet('border: 5px solid blue;')
main_panel = QtWidgets.QFrame(central_widget)
main_panel.setStyleSheet('border: 5px solid red;')
scroll_area.setWidget(main_panel)
# the crucial line: without this, main_panel will just adapt
# its size to its parent by default
main_panel.setMinimumSize(600, 500)
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
Run this and then make the window smaller using your mouse.
It's also important to be aware that some components, such as QTableView
and QTreeView
, implement scrolling components automatically.
The main thing to understand is that the scrolling happens because the child becomes too big for its parent (and its parent has set up scrolling). setMinimumSize
is a very unsubtle way to illustrate this constraint: normally the child of a scroll-enabled parent will contain certain subcomponents which at some point will have a size below which they can't be compressed... the configured layout
object of the child will also play a role in determining the minimum dimensions of the child.
Upvotes: 0
Reputation: 5136
There is an example here: https://www.learnpyqt.com/tutorials/qscrollarea/
from PyQt5.QtWidgets import (QWidget, QSlider, QLineEdit, QLabel, QPushButton, QScrollArea,QApplication,
QHBoxLayout, QVBoxLayout, QMainWindow)
from PyQt5.QtCore import Qt, QSize
from PyQt5 import QtWidgets, uic
import sys
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.scroll = QScrollArea() # Scroll Area which contains the widgets, set as the centralWidget
self.widget = QWidget() # Widget that contains the collection of Vertical Box
self.vbox = QVBoxLayout() # The Vertical Box that contains the Horizontal Boxes of labels and buttons
for i in range(1,50):
object = QLabel("TextLabel: "+str(i))
self.vbox.addWidget(object)
self.widget.setLayout(self.vbox)
#Scroll Area Properties
self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scroll.setWidgetResizable(True)
self.scroll.setWidget(self.widget)
self.setCentralWidget(self.scroll)
self.setGeometry(600, 100, 1000, 900)
self.setWindowTitle('Scroll Area Demonstration')
self.show()
return
def main():
app = QtWidgets.QApplication(sys.argv)
main = MainWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Upvotes: 3
Reputation: 120798
Make the window itself a QScrollArea
, like this:
class Window(QScrollArea):
def __init__(self):
super(Window, self).__init__()
widget = QWidget()
layout = QVBoxLayout(widget)
layout.setAlignment(Qt.AlignTop)
for index in range(100):
layout.addWidget(QLabel('Label %02d' % index))
self.setWidget(widget)
self.setWidgetResizable(True)
Upvotes: 11
Reputation: 1492
You should set layout
after adding the scroll bar
widget.
class Example(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout()
lbl_arr = makeArrayOfLabelsHTML()
for i in range(1,8):
qb = lbl_arr[i]
layout.addWidget(qb)
layout.setAlignment(Qt.AlignTop)
scroll = QScrollArea()
scroll.setWidget(self)
scroll.setWidgetResizable(True)
scroll.setFixedHeight(400)
layout.addWidget(scroll)
# set layout after adding scroll bar
self.setLayout(layout)
self.setGeometry(0, 0, 600, 220)
self.setWindowTitle('SnP watchlist')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
#print(QDesktopWidget().availableGeometry())
ex = Example()
sys.exit(app.exec_())
Upvotes: 0