Как обновить всю компоновку в шаблоне после изменения одного QWidget?

У меня есть вот такой код который при нажатии кнопки "click_me" показывает или скрывает виджет "mini_window"

from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint,
    QRect, QSize, QUrl, Qt)
from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
    QFontDatabase, QIcon, QLinearGradient, QPalette, QPainter, QPixmap,
    QRadialGradient)
from PySide2.QtWidgets import *
from PySide2.QtCore import QPropertyAnimation, QRect,QTimer
from PySide2.QtWidgets import QApplication,QWidget
import sys

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(800, 600)
        MainWindow.setStyleSheet(u"#centralwidget QWidget QWidget,\n"
"#centralwidget QWidget QWidget QWidget QWidget,\n"
"#centralwidget QWidget QWidget QWidget QWidget QWidget QWidget,\n"
"#centralwidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget,\n"
"#centralwidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget{\n"
"background:#000;\n"
"color:#fff;\n"
"}\n"
"\n"
"\n"
"#centralwidget QWidget,\n"
"#centralwidget QWidget QWidget QWidget,\n"
"#centralwidget QWidget QWidget QWidget QWidget QWidget,\n"
"#centralwidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget,\n"
"#centralwidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget{\n"
"background:#fff;\n"
"color:#000;\n"
"}\n"
"\n"
"")
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")
        self.widget = QWidget(self.centralwidget)
        self.widget.setObjectName(u"widget")
        self.widget.setGeometry(QRect(120, 30, 191, 461))
        self.verticalLayout_4 = QVBoxLayout(self.widget)
        self.verticalLayout_4.setObjectName(u"verticalLayout_4")
        self.main_winow = QWidget(self.widget)
        self.main_winow.setObjectName(u"main_winow")
        self.verticalLayout = QVBoxLayout(self.main_winow)
        self.verticalLayout.setObjectName(u"verticalLayout")
        self.click_me = QPushButton(self.main_winow)
        self.click_me.setObjectName(u"click_me")
        self.verticalLayout.addWidget(self.click_me)
        self.mini_window = QWidget(self.main_winow)
        self.mini_window.setObjectName(u"mini_window")
        self.gridLayout = QGridLayout(self.mini_window)
        self.gridLayout.setObjectName(u"gridLayout")
        self.text_label = QLabel(self.mini_window)
        self.text_label.setObjectName(u"text_label")
        self.gridLayout.addWidget(self.text_label, 0, 0, 1, 1)
        self.verticalLayout.addWidget(self.mini_window)
        self.verticalLayout_4.addWidget(self.main_winow)
        self.widget_4 = QWidget(self.widget)
        self.widget_4.setObjectName(u"widget_4")
        self.verticalLayout_2 = QVBoxLayout(self.widget_4)
        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
        self.pushButton_2 = QPushButton(self.widget_4)
        self.pushButton_2.setObjectName(u"pushButton_2")
        self.verticalLayout_2.addWidget(self.pushButton_2)
        self.widget_5 = QWidget(self.widget_4)
        self.widget_5.setObjectName(u"widget_5")
        self.gridLayout_2 = QGridLayout(self.widget_5)
        self.gridLayout_2.setObjectName(u"gridLayout_2")
        self.label_2 = QLabel(self.widget_5)
        self.label_2.setObjectName(u"label_2")
        self.gridLayout_2.addWidget(self.label_2, 0, 0, 1, 1)
        self.verticalLayout_2.addWidget(self.widget_5)
        self.verticalLayout_4.addWidget(self.widget_4)
        self.widget_6 = QWidget(self.widget)
        self.widget_6.setObjectName(u"widget_6")
        self.verticalLayout_3 = QVBoxLayout(self.widget_6)
        self.verticalLayout_3.setObjectName(u"verticalLayout_3")
        self.pushButton_3 = QPushButton(self.widget_6)
        self.pushButton_3.setObjectName(u"pushButton_3")
        self.verticalLayout_3.addWidget(self.pushButton_3)
        self.widget_7 = QWidget(self.widget_6)
        self.widget_7.setObjectName(u"widget_7")
        self.gridLayout_3 = QGridLayout(self.widget_7)
        self.gridLayout_3.setObjectName(u"gridLayout_3")
        self.label_3 = QLabel(self.widget_7)
        self.label_3.setObjectName(u"label_3")
        self.gridLayout_3.addWidget(self.label_3, 0, 0, 1, 1)
        self.verticalLayout_3.addWidget(self.widget_7)
        self.verticalLayout_4.addWidget(self.widget_6)
        self.verticalSpacer = QSpacerItem(20, 188, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.verticalLayout_4.addItem(self.verticalSpacer)
        self.verticalLayout_4.setStretch(3, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setObjectName(u"menubar")
        self.menubar.setGeometry(QRect(0, 0, 800, 21))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(u"statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.retranslateUi(MainWindow)
        QMetaObject.connectSlotsByName(MainWindow)
    # setupUi
    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
        self.click_me.setText(QCoreApplication.translate("MainWindow", u"click_me", None))
        self.text_label.setText(QCoreApplication.translate("MainWindow", u"TextLabel", None))
        self.pushButton_2.setText(QCoreApplication.translate("MainWindow", u"test", None))
        self.label_2.setText(QCoreApplication.translate("MainWindow", u"TextLabel", None))
        self.pushButton_3.setText(QCoreApplication.translate("MainWindow", u"test", None))
        self.label_3.setText(QCoreApplication.translate("MainWindow", u"TextLabel", None))
    # retranslateUi
class QtMainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self.click_me.setText('Скрыть `mini_window`')                      # +++
        self.click_me.clicked.connect(self.doAnimation)                    # +++
        QTimer.singleShot(10, self.size_mini_window)                       # +++
    def size_mini_window(self):                                            # +++
        self.s = self.mini_window.size()
    def doAnimation(self):                                                 # +++
        if self.click_me.text() == 'Скрыть `mini_window`':
            self.anim = QPropertyAnimation(self.mini_window, b"size")
            self.anim.setDuration(1500) 
            self.anim.setStartValue(self.s)
            self.anim.setEndValue(QSize(self.s.width(), 0))
            self.anim.start()
            self.click_me.setText('Показать `mini_window`')
        else:
            self.anim = QPropertyAnimation(self.mini_window, b"size")
            self.anim.setDuration(1500) 
            self.anim.setStartValue(QSize(self.s.width(), 0))
            self.anim.setEndValue(self.s)
            self.anim.start()
            self.click_me.setText('Скрыть `mini_window`')
if __name__ == '__main__':
    my = QApplication(sys.argv)
    window = QtMainWindow()
    window.show()
    sys.exit(my.exec_())    

Но проблема в том что компановка окружающих виджетов не изменилась

введите сюда описание изображения

Мне нужно что бы при нажатии кнопки внешнии виджеты тоже обновлялись

введите сюда описание изображения

Но как вы видете в моем коде такого не происходит

Как решить данную проблему?


Ответы (1 шт):

Автор решения: S. Nick

Я никогда НЕ изменяю код, сгенерированный Qt Designer'ом и мне не захотелось разбираться с этим кодом.

Я увидел вашу задачу так, попробуйте. Вам надо только поменять импорты и @QtCore.Slot(), т.к. у меня PyQt5.

import sys
import random
#from PySide2 import QtCore, QtGui, QtWidgets                   # <--- PySide2
from PyQt5 import QtCore, QtGui, QtWidgets


class CollapsibleBox(QtWidgets.QWidget):
    def __init__(self, title="", parent=None):
        super(CollapsibleBox, self).__init__(parent)

        self.toggle_button = QtWidgets.QToolButton(
            text=title, checkable=True, checked=False
        )
        self.toggle_button.setStyleSheet("QToolButton { border: none; }")
        self.toggle_button.setToolButtonStyle(
            QtCore.Qt.ToolButtonTextBesideIcon
        )
        self.toggle_button.setArrowType(QtCore.Qt.RightArrow)
        self.toggle_button.pressed.connect(self.on_pressed)

        self.toggle_animation = QtCore.QParallelAnimationGroup(self)

        self.content_area = QtWidgets.QScrollArea(
            maximumHeight=0, minimumHeight=0
        )
        self.content_area.setSizePolicy(
            QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed
        )
        self.content_area.setFrameShape(QtWidgets.QFrame.NoFrame)

        lay = QtWidgets.QVBoxLayout(self)
        lay.setSpacing(0)
        lay.setContentsMargins(0, 0, 0, 0)
        lay.addWidget(self.toggle_button)
        lay.addWidget(self.content_area)

        self.toggle_animation.addAnimation(
            QtCore.QPropertyAnimation(self, b"minimumHeight")
        )
        self.toggle_animation.addAnimation(
            QtCore.QPropertyAnimation(self, b"maximumHeight")
        )
        self.toggle_animation.addAnimation(
            QtCore.QPropertyAnimation(self.content_area, b"maximumHeight")
        )

#    @QtCore.Slot()                                                    # <--- PySide2
    @QtCore.pyqtSlot()
    def on_pressed(self):
        checked = self.toggle_button.isChecked()
        self.toggle_button.setArrowType(
            QtCore.Qt.DownArrow if not checked else QtCore.Qt.RightArrow
        )
        self.toggle_animation.setDirection(
            QtCore.QAbstractAnimation.Forward
            if not checked
            else QtCore.QAbstractAnimation.Backward
        )
        self.toggle_animation.start()

    def setContentLayout(self, layout):
        lay = self.content_area.layout()
        del lay
        self.content_area.setLayout(layout)
        collapsed_height = (
            self.sizeHint().height() - self.content_area.maximumHeight()
        )
        content_height = layout.sizeHint().height()
        for i in range(self.toggle_animation.animationCount()):
            animation = self.toggle_animation.animationAt(i)
            animation.setDuration(500)
            animation.setStartValue(collapsed_height)
            animation.setEndValue(collapsed_height + content_height)

        content_animation = self.toggle_animation.animationAt(
            self.toggle_animation.animationCount() - 1
        )
        content_animation.setDuration(500)
        content_animation.setStartValue(0)
        content_animation.setEndValue(content_height)

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        centralWidget = QtWidgets.QWidget()
        self.setCentralWidget(centralWidget)
        vlay = QtWidgets.QVBoxLayout(centralWidget) 

        for i in range(3):
            box = CollapsibleBox("Collapsible Box Header-{}".format(i))
            vlay.addWidget(box)
            lay = QtWidgets.QVBoxLayout()
            lay.setSpacing(0)
            lay.setContentsMargins(0, 0, 0, 0)
            for j in range(3):
                label = QtWidgets.QLabel("Label {}-{}".format(i, j))
                color = QtGui.QColor(*[random.randint(0, 255) for _ in range(3)])
                label.setStyleSheet(
                    "background-color: {}; color : white;".format(color.name())
                )
                label.setAlignment(QtCore.Qt.AlignCenter)
                label.setMaximumWidth(150)
                label.setMinimumHeight(25)
                textButton = "Button {}-{}".format(i, j) 
                pushButton = QtWidgets.QPushButton(textButton, 
                    clicked=lambda _, t=textButton: print(t))
                pushButton.setMaximumWidth(150)
                pushButton.setMinimumHeight(25)
                lay.addWidget(pushButton)
                lay.addWidget(label)

            box.setContentLayout(lay)

        vlay.addStretch()        


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.resize(640, 570)
    w.show()
    sys.exit(app.exec_())

введите сюда описание изображения

→ Ссылка