Home > Net >  QDialog with scrollbars visible only when content is bigger than the size
QDialog with scrollbars visible only when content is bigger than the size

Time:07-13

How can I make the QDialog to resize according to the content, and, if the content is larger than the screen size, resize the dialog to the screen size and display scrollbars (horizontal and vertical)?

To provide some context:

I created class inheriting from QDialog that I use as a generic dialog (from which I create curstom error, warning and info dialogs), and I want to add a QScrollArea, so when the content is larger than the screen size, the dialog resizes to the screen size (whether it's the width, the height or both that extend).

In order to make the dialog flexible to the content, I use adjustSize(). But when I have a content that is bigger than the screen size, the QScrollArea does not take the screen size even if I override the sizeHint to be self.screen().size().

I will create a small sample and update the post tomorrow morning (but wanted to have it written in case someone has an idea of how to do it).

CodePudding user response:

This is how I fixed it, following the approach mentioned in this other post Cannot automatically resize a QScrollArea

import sys
import os

from PySide2.QtCore import QFile, QIODevice, QTextStream, QSize, QTimer
from PySide2.QtWidgets import QWidget, QHBoxLayout, QLabel, QDialog, QScrollArea, QFrame, QApplication, QStyle

_SAMPLE_FILE_PATH: str = 'sample.txt'


def get_text_from_file(file_path: str) -> str:
    text: str = ""
    file_path = os.path.join(os.path.dirname(__file__), file_path)
    if QFile.exists(file_path):
        file = QFile(file_path)
        if file.open(QIODevice.ReadOnly | QIODevice.Text):
            stream = QTextStream(file)
            text = stream.readAll()
        file.close()
    else:
        print('file does not exist')
    return text


class ScrollBaseDialog(QDialog):
    def __init__(
            self,
            title: str,
            content: QWidget):
        super(ScrollBaseDialog, self).__init__()

        self.setWindowTitle(title)
        self._scroll_area = QScrollArea(self)
        self._scroll_area.setWidget(content)
        self._content = content

        self._scroll_area.setWidgetResizable(True)
        self._scroll_area.setFrameShape(QFrame.NoFrame)

        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self._scroll_area)
        self.setLayout(layout)
        self.adjustSize()
        QTimer.singleShot(0, self._adjust_geometry)

    def _adjust_geometry(self) -> None:
        header_height = self.style().pixelMetric(QStyle.PM_TitleBarHeight)
        scroll_width = self.style().pixelMetric(QStyle.PM_ScrollBarExtent)

        max_size = self.screen().availableSize() - QSize(scroll_width, header_height)  # screen_size - header
        width = min(max_size.width(), self._content.width())   scroll_width  # scrollbar width
        height = min(max_size.height(), self._content.height())

        x: int = self.screen().geometry().x()   scroll_width/2   (max_size.width() - width) / 2
        y: int = self.screen().geometry().y()   header_height   (max_size.height() - height) / 2
        self.setGeometry(x, y, width, height)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    dialog = ScrollBaseDialog(title='Sample Dialog', content=QLabel(get_text_from_file(_SAMPLE_FILE_PATH)))
    dialog.show()
    sys.exit(app.exec_())
  • Related