Как реализовать собственную QScrollArea - PullRequest
0 голосов
/ 23 апреля 2020

Я пытаюсь понять, как QScrollArea работает над реализацией моего собственного MyQScrollArea виджета. MyQScrollArea должен использовать setViewportMargins . Для этого я написал минимальный рабочий пример, показанный ниже:

from PyQt5 import QtWidgets
import sys

class MyScrollArea(QtWidgets.QAbstractScrollArea):
    def __init__(self):
        super().__init__()

        self.label = QtWidgets.QLabel(", ".join(map(str, range(100))), self)

        hScrollBar = self.horizontalScrollBar()

        hScrollBar.setRange(0, self.label.sizeHint().width() - self.sizeHint().width())
        hScrollBar.valueChanged.connect(self._HScrollBarValueChanged)

        self.setViewportMargins(100, 0, 0, 0)
        self._HScrollBarValueChanged(0)

    def _HScrollBarValueChanged(self, value):
        self.label.move(-value + self.viewportMargins().left(), 0)

def main():
    app = QtWidgets.QApplication(sys.argv)
    scroll = MyScrollArea()
    scroll.show()
    app.exec_()

if __name__ == "__main__":
    main()

Результат кода показан ниже:

Widget before scrolling

Однако после прокрутки внутренний виджет выходит из области просмотра и рисует себя в области, которую я не хочу, чтобы он рисовал:

Widget after scrolling

Что я делаю что-то не так и как мне заставить работать setViewportMargins функциональность?

1 Ответ

2 голосов
/ 23 апреля 2020

Вы должны установить его как QLabel как дочерний элемент окна просмотра, в дополнение к изменению свойств QScrollBar каждый раз, когда изменяется геометрия виджетов:

import sys

from PyQt5 import QtWidgets


class MyScrollArea(QtWidgets.QAbstractScrollArea):
    def __init__(self):
        super().__init__()

        self.label = QtWidgets.QLabel(", ".join(map(str, range(100))), self.viewport())

        self.setViewportMargins(100, 0, 0, 0)
        self.horizontalScrollBar().valueChanged.connect(
            self.on_hscrollbar_value_changed
        )
        self.update_scrollbar()

    def on_hscrollbar_value_changed(self, value):
        self.label.move(-value, 0)

    def update_scrollbar(self):
        self.horizontalScrollBar().setRange(
            0, self.label.sizeHint().width() - self.viewport().width()
        )
        self.horizontalScrollBar().setPageStep(self.viewport().width())

    def resizeEvent(self, event):
        self.update_scrollbar()
        super().resizeEvent(event)


def main():
    app = QtWidgets.QApplication(sys.argv)
    scroll = MyScrollArea()
    scroll.show()
    app.exec_()


if __name__ == "__main__":
    main()
...