为什么我尝试使其可折叠的QToolButton无法正确折叠?

问题描述 投票:0回答:1

人。

寻求您的帮助来对我的测试脚本进行故障排除。我正在练习制作带有小部件的可折叠按钮。

脚本主要取自关于折叠按钮的stackoverflow中的another question

所以我试图将我的QTabWidget放在class CollpsibleBox(QWidget)下。问题是我的CollapsibleBox动作很奇怪-按钮在跳动,有时无法正确打开/关闭。

我想知道将我的小部件正确放置在QTabWidget下是否有些错误,或者动画是否存在某些问题?

import random
from PySide2.QtGui import QPixmap, QBrush, QColor, QIcon, QPainterPath, QPolygonF, QPen, QTransform
from PySide2.QtCore import QSize, Qt, Signal, QPointF, QRect, QPoint, QParallelAnimationGroup, QPropertyAnimation, QAbstractAnimation
from PySide2.QtWidgets import QMainWindow, QDialog, QVBoxLayout, QHBoxLayout, QGraphicsView, QGraphicsScene, QFrame, \
    QSizePolicy, QGraphicsPixmapItem, QApplication, QRubberBand, QMenu, QMenuBar, QTabWidget, QWidget, QPushButton, \
    QSlider, QGraphicsPolygonItem, QToolButton, QScrollArea, QLabel

extraDict = {'buttonSetA': ['test'], 'buttonSetB': ['test']}
tabList = ['Main', 'Extra']
_ui = dict()

class MainWindow(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self, parent=parent)
        self.create()

    def create(self, **kwargs):
        _ui['mainLayout'] = QVBoxLayout()
        _ui['tabWidget'] = QTabWidget()
        _ui['mainLayout'].addWidget(_ui['tabWidget'])
        for tab in tabList:
            _ui['tab' + tab] = QWidget()
            _ui['tabWidget'].addTab(_ui['tab' + tab], tab)

        _ui['tabExtra'].layout = QVBoxLayout()
        _ui['tabExtra'].setLayout(_ui['tabExtra'].layout)

        _ui['content'] = QWidget()
        _ui['tabExtra'].layout.addWidget(_ui['content'])

        vlay = QVBoxLayout(_ui['content'])
        for name in extraDict.keys():
            box = CollapsibleBox(name)
            vlay.addWidget(box)
            lay = QVBoxLayout()
            for j in range(8):
                label = QLabel("{}".format(j))
                color = QColor(*[random.randint(0, 255) for _ in range(3)])
                label.setStyleSheet(
                    "background-color: {}; color : white;".format(color.name())
                )
                label.setAlignment(Qt.AlignCenter)
                lay.addWidget(label)

            box.setContentLayout(lay)
        self.setLayout(_ui['mainLayout'])

class CollapsibleBox(QWidget):
    def __init__(self, name):
        super(CollapsibleBox, self).__init__()
        self.toggle_button = QToolButton(text=name, checkable=True, checked=False)
        self.toggle_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.toggle_button.setArrowType(Qt.RightArrow)
        self.toggle_button.pressed.connect(self.on_pressed)
        self.toggle_animation = QParallelAnimationGroup(self)
        self.content_area = QScrollArea(maximumHeight=0, minimumHeight=0)
        self.content_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.content_area.setFrameShape(QFrame.NoFrame)

        lay = 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(QPropertyAnimation(self, b"minimumHeight"))
        self.toggle_animation.addAnimation(QPropertyAnimation(self, b"maximumHeight"))
        self.toggle_animation.addAnimation(QPropertyAnimation(self.content_area, b"maximumHeight"))

    def on_pressed(self):
        checked = self.toggle_button.isChecked()
        self.toggle_button.setArrowType(Qt.DownArrow if not checked else Qt.RightArrow)
        self.toggle_animation.setDirection(QAbstractAnimation.Forward
            if not checked
            else 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)

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    window = MainWindow()
    window.setGeometry(500, 100, 500, 500)
    window.show()
    sys.exit(app.exec_())
python pyqt
1个回答
1
投票

问题是,您只向整个布局添加了两个小部件,并且布局将尝试将它们放置得尽可能好(通常根据其大小提示,将其放置在每个小部件可用区域的中心)。 。

您可以设置布局的小部件的对齐方式(将按钮放在其可用空间的顶部):

        vlay = QVBoxLayout(_ui['content'])
        for name in extraDict.keys():
            box = CollapsibleBox(name)
            vlay.addWidget(box, alignment=Qt.AlignTop)

或在布局的底部添加一个拉伸:

        vlay = QVBoxLayout(_ui['content'])
        for name in extraDict.keys():
            # ...
        vlay.addStretch(1)

将所有按钮放置在布局顶部。

作为旁注,我建议您避免使用ui的字典逻辑,因为它可能变得非常混乱并且容易出错。如果您确实出于某些原因(我希望非常好)这样做,但是请在提问时避免使用它:这使really难以阅读您的代码,并且人们可能最终只是完全不理会您的问题。

© www.soinside.com 2019 - 2024. All rights reserved.