Python Forum
[PyQt] How do I get a QScrollArea to scroll? - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: GUI (https://python-forum.io/forum-10.html)
+--- Thread: [PyQt] How do I get a QScrollArea to scroll? (/thread-35342.html)



How do I get a QScrollArea to scroll? - LavaCreeperKing - Oct-22-2021

A lot of people seem to have this problem. How do I get a QScrollArea to scroll. I have this code below that creates widgets and places them in lines in a QScrollArea to display information. I need to set 4 widgest per line and space them out properly to display all the needed information. The problem in I cant get the ScrollArea to scroll.

(Using PyQt5)

self.pkg_display = QtWidgets.QScrollArea(self)
self.pkg_display.setGeometry(10, 40, 801, 401)
self.pkg_display.setStyleSheet("background-color: White")
self.pkg_display.setVerticalScrollBarPolicy(2)
self.pkg_display.setWidgetResizable(True)
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(0, 0, 801, 800)
self.pkg_display.setWidget(self.scrollAreaWidgetContents)
def update_list():
    pos = 0
    x1 = 10
    y1 = 2
    x2 = 393
    y2 = 5
    x3 = 700
    x4 = 756
    for i in filtered_name:
        cb = QtWidgets.QCheckBox(ui.scrollAreaWidgetContents)
        cb.setGeometry(x1,y1,361,23)
        cb.setText(i)
        vtext = QtWidgets.QLabel(ui.scrollAreaWidgetContents)
        vtext.setGeometry(x2,y2,291,17)
        vtext.setText(filtered_version[pos])
        stext = QtWidgets.QLabel(ui.scrollAreaWidgetContents)
        stext.setGeometry(x3,y2,51,17)
        stext.setText(filtered_size[pos])
        ib = QtWidgets.QPushButton(ui.scrollAreaWidgetContents)
        ib.setGeometry(x4,y1,21,21)
        ib.setText("i")
        y1 += 23
        y2 += 23
        pos += 1
    ui.pkg_display.update()
The code creates the widjets and places them in the ScrollArea(pkg_dsiplay), but it will not scroll.
If anyone is wondering I am working on a tool to replace dnfdrogora(A Linux graphical package manager tool)


RE: How do I get a QScrollArea to scroll? - Axel_Erfurt - Oct-22-2021

Nobody can really help with a few snippets of code.

Example PyQt5 GUI Creating QScrollArea


RE: How do I get a QScrollArea to scroll? - LavaCreeperKing - Oct-23-2021

(Oct-22-2021, 08:08 PM)Axel_Erfurt Wrote: Nobody can really help with a few snippets of code.

Example PyQt5 GUI Creating QScrollArea

Here is a full example of how I am creating the the window, scrollarea, and widgets.
import sys
import subprocess
from PyQt5 import QtWidgets

filtered_name = []
filtered_version = []
filtered_size = []
app = QtWidgets.QApplication(sys.argv)

class MyWindow(QtWidgets.QMainWindow):
    def setup(self):
        QtWidgets.QMainWindow.__init__(self)
        self.resize(820, 625)
        self.setWindowTitle("PkgMgr")
        self.setMaximumSize(820, 620)
        self.setMinimumSize(16, 9)

        self.uninstallB = QtWidgets.QPushButton(self)
        self.uninstallB.setGeometry(10, 10, 111, 25)
        self.uninstallB.setText("Uninstall")

        self.clear_selectB = QtWidgets.QPushButton(self)
        self.clear_selectB.setGeometry(130, 10, 111, 25)
        self.clear_selectB.setText("Clear Selection")

        self.searchB = QtWidgets.QPushButton(self)
        self.searchB.setGeometry(620, 10, 91, 25)
        self.searchB.setText("Search")

        self.clear_searchB = QtWidgets.QPushButton(self)
        self.clear_searchB.setGeometry(720, 10, 91, 25)
        self.clear_searchB.setText("Clear Search")

        self.search_bar = QtWidgets.QLineEdit(self)
        self.search_bar.setGeometry(450, 10, 161, 25)

        self.pkg_display = QtWidgets.QScrollArea(self)
        self.pkg_display.setGeometry(10, 40, 801, 401)
        self.pkg_display.setStyleSheet("background-color: White")
        self.pkg_display.setVerticalScrollBarPolicy(2)
        self.pkg_display.setWidgetResizable(True)
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(0, 0, 801, 800)
        self.pkg_display.setWidget(self.scrollAreaWidgetContents)

        self.info_display = QtWidgets.QTextBrowser(self)
        self.info_display.setGeometry(10, 450, 801, 161)

def get_package(mode):
    cmd = subprocess.Popen("dnf info -C --installed", shell=True, stdout=subprocess.PIPE)
    raw_out = cmd.stdout.readlines()
    vpos = 0
    for l in raw_out:
        l = str(l)
        size = l.find("b'Size")
        name = l.find("b'Name")
        version = l.find("b'Version")
        release = l.find("b'Release")
        if name != -1:
            line = l[name+17:len(l)-3]
            filtered_name.append(line)
        elif version != -1:
            line = l[version+17:len(l)-3]
            filtered_version.append(line)
        elif release != -1:
            line = l[release+17:len(l)-3]
            filtered_version[vpos] += "-" + line
            vpos += 1
        elif size != -1:
            line = l[size+17:len(l)-3]
            filtered_size.append(line)

def update_list():
    pos = 0
    x1 = 10
    y1 = 2
    x2 = 393
    y2 = 5
    x3 = 700
    x4 = 756
    for l in filtered_name:
        cb = QtWidgets.QCheckBox(ui.scrollAreaWidgetContents)
        cb.setGeometry(x1,y1,361,23)
        cb.setText(l)
        vtext = QtWidgets.QLabel(ui.scrollAreaWidgetContents)
        vtext.setGeometry(x2,y2,291,17)
        vtext.setText(filtered_version[pos])
        stext = QtWidgets.QLabel(ui.scrollAreaWidgetContents)
        stext.setGeometry(x3,y2,51,17)
        stext.setText(filtered_size[pos])
        ib = QtWidgets.QPushButton(ui.scrollAreaWidgetContents)
        ib.setGeometry(x4,y1,21,21)
        ib.setText("i")
        y1 += 23
        y2 += 23
        pos += 1
    ui.pkg_display.update()
    
ui = MyWindow()
ui.setup()
get_package(0)
update_list()
ui.show()
sys.exit(app.exec_())



RE: How do I get a QScrollArea to scroll? - deanhystad - Oct-24-2021

I cannot run your example (I have PySide2) and translating to PySide2 is difficult because of how you use the designer (which I hate hate hate hate designer code).

This is a short example of a working scrollable area.
import sys
import PySide2.QtWidgets as QtWidgets
from PySide2.QtCore import Qt

class MyWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.view = QtWidgets.QWidget()
        self.layout = QtWidgets.QVBoxLayout(self.view)
        self.scroll = QtWidgets.QScrollArea(self)
        self.scroll.setWidgetResizable(True)
        self.scroll.setWidget(self.view)
        self.setCentralWidget(self.scroll)
        for i in range(20):
            self.layout.addWidget(QtWidgets.QLabel('Make this a fairly wide Label '+str(i)))
     
app = QtWidgets.QApplication(sys.argv)
ui = MyWindow()
ui.show()
sys.exit(app.exec_())
The important parts are that the scrolled widget is larger than the scrollable area and that the scrollable area knows how big the scrolled widget is (setWidgetResizeable(True)).

Looking at your example I think the problem is that the scrolled widget is not larger than the scrollable area. I'm guessing that ui.scrollAreaWidgetContents is your scrolled widget (a QWidget?). I see where you place things in this widget but I don't see where the widget is resized. I would stop using setGeometry and use a layout manager instead. That will automatically grow the scrolled widget as needed.


RE: How do I get a QScrollArea to scroll? - Axel_Erfurt - Oct-24-2021

Why don't you just use a QTableWidget with checkboxes?

Here is a simple example (for apt, since I use mint)

[Image: test55.png?raw=1]

import sys
import subprocess
from PyQt5 import QtWidgets, QtCore
 
filtered_name = []
filtered_version = []
filtered_size = []
app = QtWidgets.QApplication(sys.argv)
 
class MyWindow(QtWidgets.QMainWindow):
    def setup(self):
        QtWidgets.QMainWindow.__init__(self)
        self.resize(820, 625)
        self.setWindowTitle("PkgMgr")
        self.setMaximumSize(820, 620)
        self.setMinimumSize(16, 9)
 
        self.table = QtWidgets.QTableWidget()
        self.table.setColumnCount(3)
        self.table.setHorizontalHeaderLabels(["", "Name", "Version"])
        self.setCentralWidget(self.table)
 
    def get_package(self, mode):
        cmd = subprocess.Popen("apt list --installed", shell=True, stdout=subprocess.PIPE)
        raw_out = cmd.stdout.readlines()
        for l in raw_out[1:]:
            name = l.decode().partition("/")[0]
            version = l.decode().partition("/")[2].partition(",now ")[2]
            print(name, version)
            filtered_name.append(name)
            filtered_version.append(version)
 
    def update_list(self):
        for x in range(len(filtered_name)):
            self.table.insertRow(x)
            item = QtWidgets.QTableWidgetItem('uninstall')
            item.setFlags(QtCore.Qt.ItemIsUserCheckable |
                                  QtCore.Qt.ItemIsEnabled)
            item.setCheckState(QtCore.Qt.Unchecked)
            self.table.setItem(x, 0, item)            
            self.table.setItem(x, 1, QtWidgets.QTableWidgetItem(filtered_name[x]))
            self.table.setItem(x, 2, QtWidgets.QTableWidgetItem(filtered_version[x]))
        self.table.resizeColumnsToContents()

     
ui = MyWindow()
ui.setup()
ui.get_package(0)
ui.update_list()
ui.show()
sys.exit(app.exec_())



RE: How do I get a QScrollArea to scroll? - LavaCreeperKing - Oct-24-2021

"The important parts are that the scrolled widget is larger than the scrollable area and that the scrollable area knows how big the scrolled widget is (setWidgetResizeable(True))."

But when I do self.scrollAreaWidgetContents.setGeometry(0, 0, 801, 800) or self.scrollAreaWidgetContents.resize(801,800) is that not making it larger than pkg_display(self.pkg_display.setGeometry(10, 40, 801, 401)? The problem I have with layout managers is I can't control where my widgets are placed or how big/small they are.

@Axel_Erfurt
Yes I could do that, but this the effect that I wanted to achieve.
[attachment=1345]

EDIT: So I just removed self.pkg_display.setWidgetResizable(True) from my code... and now my scroll area works just fine.


RE: How do I get a QScrollArea to scroll? - Axel_Erfurt - Oct-24-2021

Using setGeometry is not a good idea. A BoxLayout (HBox, VBox) or GridLayout is better.


RE: How do I get a QScrollArea to scroll? - deanhystad - Oct-26-2021

I agree that setGeometry is a bad idea. Your example is easily achieved using a grid layout manager.


RE: How do I get a QScrollArea to scroll? - LavaCreeperKing - Oct-28-2021

(Oct-26-2021, 08:05 PM)deanhystad Wrote: I agree that setGeometry is a bad idea. Your example is easily achieved using a grid layout manager.

Then could you please give me an example? I don't know how to use layout managers.


RE: How do I get a QScrollArea to scroll? - Axel_Erfurt - Oct-29-2021

Layouts

all examples