3

Well. The question seems to be very easy, but the result I get is different from what I expect to.

I have an app, which height depends on its content. Here is auto-resize code:

def resizeApp(self):
    n = len(self.listOfWidgets) 
    if self.screenHEIGHT - 40 > n * 125 + 50:
        self.resize(self.width(), n * 125 + 50)
        self.scrollArea.resize(self.scrollArea.width(), n * 125 + 20)
    else:
        self.resize(self.width(), self.screenHEIGHT - 40)
        self.scrollArea.resize(self.scrollArea.width(), self.screenHEIGHT - 40 - 30)
    print(self.scrollArea.verticalScrollBar().isVisible())

You can see that after the resize we can define the visibility of the verticalScrollbar. Look at the app and console screenshot. We can see the that app has verticalScrollbar, but console says that it doesn't. It seems isVisible() lags a bit and tells me previous state.

For example. When I add widgets, while there is no verticalScrollbar, the console says False (verticalScrollbar is not visible). When the amount of widgets requires verticalScrollbar, scrollArea creates this verticalScrollbar, however I receive message that the verticalScrollbar is not visible. And later, after adding one more widget, I get message that the verticalScrollbar is visible.

And vice versa. When I delete widgets, I receive message that the verticalScrollbar is visible after one more widget is deleted. However it should say me "False" one step earlier.

Am I missing something?

UPDATE1. As requested, I add a working example without redundant code. You can download a zip archive from my dropbox >here<

>Virustotal.com analysis<

App screenshot

Devilhunter
  • 123
  • 2
  • 11

2 Answers2

2

Let's suppose you override your QScrollArea class, so you just have to set the policies of it, it would be something like that:

self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

In this way you choose whatever bar you want to see, when, and which one, just have to set these policies when you need.

Here is a QScrollArea I've done some time ago, that totally worked for me:

"""It takes care of the scroll area with slides."""

# !/usr/bin/python
# -*- coding: utf-8 -*-

from PyQt5.QtCore import QPoint
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QScrollArea


class ScrollArea(QScrollArea):
    """ScrollArea is a personalized scroll area."""

    initial_pos = QPoint()
    pressed = False

    def __init__(self, parent=None):
        """Init UI."""

        super(ScrollArea, self).__init__(parent)
        self.init_ui()

    def init_ui(self):
        """Init all ui object requirements."""

        self.setFixedWidth(200)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setStyleSheet("""

            QScrollArea{
                background-color:transparent;
                border-top-right-radius: 4px;
                border-top-left-radius: 4px;
                border-bottom-right-radius: 4px;
                border-bottom-left-radius: 4px;
                border: 0px solid ;
                border-color: rgb(0,0,0,100)
            }

            QScrollBar:vertical{
                border:1px solid;
                border-color: rgb(197,197,199,100);
                width: 7px;
                margin: 0px 0px 0px 0px;
                background: rgb(234,234,234,100);


            }

            QScrollBar::handle:vertical  {
                background: rgba(14,65,148,100);
            }

            QScrollBar::add-line:vertical{
                height: 0px;
            }

            QScrollBar::sub-line:vertical{
                height: 0px;
            }

        """)

        self.setWidgetResizable(True)

    def mousePressEvent(self, event):
        """Update initial click location of scroll area."""

        self.pressed = True
        self.initial_pos = self.verticalScrollBar().value() + event.pos().y()

    def mouseReleaseEvent(self, event):
        """Update next location to be used in scroll area location."""

        self.pressed = False
        self.initial_pos = self.verticalScrollBar().value()

    def mouseMoveEvent(self, event):
        """Update value location of scroll area according to init location."""
        if self.pressed:
            self.verticalScrollBar().setValue(
                 self.initial_pos - event.pos().y())
yurisnm
  • 1,630
  • 13
  • 29
0

After trying to apply many different solutions, I've come to the easiest one. This one isn't the most proper, however it solves my problem.

If I have two branches of code, which determine widget height and depend on the amount of inner widgets, therefore I can predict when I need scrollbar. That's why we can change main widget's width in these two branches of "if". Here is how the resize function was changed:

def resizeApp(self):
    n = len(self.listOfWidgets) 
    if self.screenHEIGHT - 40 > n * 125 + 50:
        self.resize(135, n * 125 + 50)
        self.scrollArea.resize(self.scrollArea.width(), n * 125 + 20)
    else:
        self.resize(150, self.screenHEIGHT - 40)
        self.scrollArea.resize(self.scrollArea.width(), self.screenHEIGHT - 40 - 30)

And that's it!

Devilhunter
  • 123
  • 2
  • 11