pyqt5 наследование QScrollArea

Мне трудно понять, как использовать полосы прокрутки в PyQt5. У меня есть произвольный макет для экспериментов, который состоит из нескольких блоков цветов. Я хотел бы, чтобы расположение цветов имело минимальный размер, а когда окно меньше этого, появляются полосы прокрутки (или полосы прокрутки просто присутствуют все время). Я нашел этот пример:

PyQt: поместите полосы прокрутки в это

и изменил его для работы с PyQt5:

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

from PyQt5 import QtCore, QtGui
from PyQt5.QtWidgets import QDialog, QApplication, QPushButton, QScrollArea, QVBoxLayout, QWidget
class myDialog(QDialog):
    _buttons = 0

    def __init__(self, parent=None):
        super(myDialog, self).__init__(parent)
        self.pushButton = QPushButton(self)
        self.pushButton.setText("Add Button!")
        self.pushButton.clicked.connect(self.on_pushButton_clicked)
        self.scrollArea = QScrollArea(self)
        self.scrollArea.setWidgetResizable(True)
        self.scrollAreaWidgetContents = QWidget(self.scrollArea)
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 380, 247))
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.addWidget(self.pushButton)
        self.verticalLayout.addWidget(self.scrollArea)
        self.verticalLayoutScroll = QVBoxLayout(self.scrollAreaWidgetContents)
'''
verticalLayoutScroll is a child of scrollAreaWidgetContents
scrollAreaWidgetContents is a child of scrollArea
scrollArea is child of self

verticalLayout is also a child of self has the widgets pushButton and scrollArea
'''
    @QtCore.pyqtSlot()
    def on_pushButton_clicked(self):
        self._buttons  += 1
        pustButtonName = u"Button {0}".format(self._buttons)

        pushButton = QPushButton(self.scrollAreaWidgetContents)
        pushButton.setText(pustButtonName)

        self.verticalLayoutScroll.addWidget(pushButton)


if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    app.setApplicationName('myDialog')
    main = myDialog()
    main.show()
    sys.exit(app.exec_())

Вот мой код:

    # -*- coding: utf-8 -*-
"""
Created on Mon Jan 15 07:37:28 2018

@author: Erik
"""
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QSlider, QPushButton, 
QMainWindow, QAction, qApp,
    QLCDNumber, QGridLayout, QLabel, QLineEdit, QVBoxLayout, QHBoxLayout, 
QSizePolicy, QScrollArea, QLayout)
from PyQt5.QtGui import QIcon, QColor, QPalette
from PyQt5.QtCore import Qt, QSize, QRect

class Color(QWidget):

    def __init__(self, color, *args, **kwargs):
        super(Color, self).__init__(*args, **kwargs)
        self.setAutoFillBackground(True)

        palette = self.palette()
        palette.setColor(QPalette.Window, QColor(color))
        self.setPalette(palette)

class Color2(QWidget):

    def __init__(self, color, *args, **kwargs):
        super(Color2, self).__init__(*args, **kwargs)
        self.setAutoFillBackground(True)
        palette = self.palette()
        palette.setColor(QPalette.Window, QColor(color))
        self.setPalette(palette)

    def sizeHint(self):
        return QSize(150,150)

class MainWindow(QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.setWindowTitle("My Awesome App")

        size = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)

        layout = QVBoxLayout()
        layout2 = QVBoxLayout()
        brw = Color2('brown')
        brw.setSizePolicy(size)
        layout2.addWidget(brw)
        layout2.addWidget(Color('black'))
        layout2.setStretch(1,2)
        layout2.addWidget(Color('cyan'))
        layout2.setStretch(2, 1)

        layout.addWidget(Color('red'))
        layout.addWidget(Color('blue'))
        layout.addWidget(Color('green'))


        self.scrollArea = QScrollArea(self)
        self.scrollArea.setWidgetResizable(True)
        self.scrollAreaWidgetContents = QWidget(self.scrollArea)
        self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 600, 500))   
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.scrollAreaWidgetContents.setMinimumSize(QSize(500, 500))

        self.scrollLayout = QVBoxLayout(self.scrollAreaWidgetContents)
        #self.scrollLayout.setSizeConstraint(QLayout.SetMinimumSize) #2
        self.mainLayout = QHBoxLayout()
        self.mainLayout.addWidget(Color('purple'))
        self.mainLayout.addWidget(Color('yellow'))
        self.mainLayout.addWidget(Color('orange'))
        self.mainLayout.addLayout(layout2)
        self.mainLayout.addLayout(layout)
        self.scrollLayout.addLayout(self.mainLayout)

        self.show()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = MainWindow()
    sys.exit(app.exec_())

Я едва вижу цвета в области прокрутки. В первом блоке кода выше я не понимаю необходимую структуру наследования, описанную в блоке комментариев. Нужно ли расширять класс макета, чтобы установить минимальный размер? https://doc.qt.io/qt-5/qlayoutitem.html#minimumSize Как устроен раздел «Подсказки по размеру и макеты» на сайте https://doc.qt.io/qt-5/qscrollarea.html#details актуально?
Спасибо.


person Erik Iverson    schedule 05.04.2018    source источник


Ответы (1)


Проблема в том, что вы не установили QScrollArea как CentralWidget.

class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setWindowTitle("My Awesome App")

        size = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)

        layout = QVBoxLayout()
        layout2 = QVBoxLayout()
        brw = Color2('brown')
        brw.setSizePolicy(size)
        layout2.addWidget(brw)
        layout2.addWidget(Color('black'))
        layout2.setStretch(1,2)
        layout2.addWidget(Color('cyan'))
        layout2.setStretch(2, 1)

        layout.addWidget(Color('red'))
        layout.addWidget(Color('blue'))
        layout.addWidget(Color('green'))

        self.scrollArea = QScrollArea()
        # set CentralWidget
        self.setCentralWidget(self.scrollArea)

        self.scrollArea.setWidgetResizable(True)
        self.scrollAreaWidgetContents = QWidget(self.scrollArea)
        self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 600, 500))   
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.scrollAreaWidgetContents.setMinimumSize(QSize(500, 500))

        self.scrollLayout = QVBoxLayout(self.scrollAreaWidgetContents)
        #self.scrollLayout.setSizeConstraint(QLayout.SetMinimumSize) #2
        self.mainLayout = QHBoxLayout()
        self.mainLayout.addWidget(Color('purple'))
        self.mainLayout.addWidget(Color('yellow'))
        self.mainLayout.addWidget(Color('orange'))
        self.mainLayout.addLayout(layout2)
        self.mainLayout.addLayout(layout)
        self.scrollLayout.addLayout(self.mainLayout)

        self.show()
person eyllanesc    schedule 05.04.2018
comment
Спасибо! Он делает то, что я хочу сейчас. Можете ли вы сказать мне, какова цель scrollAreaWidgetContents? - person Erik Iverson; 06.04.2018
comment
@ErikIverson QScrollArea — это виджет, единственной задачей которого является управление полосами прокрутки, когда они необходимы, контейнер, в случае scrollAreaWidgetContents — это содержимое, и оно должно быть уникальным, если вы хотите разместить несколько виджетов, эти виджеты должны быть часть scrollAreaWidgetContents. Если мой ответ помог, не забудьте отметить его как правильный, если вы не знаете, как это сделать, просмотрите тур, это лучший способ поблагодарить. - person eyllanesc; 06.04.2018
comment
Я отметил это как правильное. Еще один вопрос - если scrollAreaWidgetContents инициализирован/объявлен как дочерний элемент scrollArea, почему все еще необходимо использовать self.scrollArea.setWidget(self.scrollAreaWidgetContents)? - person Erik Iverson; 06.04.2018