Qt resize layout during widget 属性 动画

Qt resize layout during widget property animation

我有一个正在完善的现有应用程序,我想为一些小部件添加一些动画。在布局之外使用 QPropertyAnimation 为小部件设置动画既简单又有趣,但是当它们位于布局中时,我遇到了各种困难。目前让我头疼的是,当我为小部件的大小设置动画时,布局不会调整到它的新大小。

所以假设我有一个带有三个小部件的 QVBoxLayout:一个应该扩展到所有可用的标签 space、一个树视图和一个按钮。当我单击按钮时,我希望树折叠并且标签接管它 space。下面是代码中的这个示例,正如您所看到的,当树对其大小进行动画处理时没有任何反应,然后当我在动画结束时将其隐藏时,标签会弹出以填充现在的空缺 space。所以看起来在动画期间布局不会 "know" 树正在调整大小。我想要发生的是随着树的缩小,标签会扩展以填充它。

这是否可以不通过标签的绝对大小来完成,而是通过在布局上调用调整大小或类似的方法来完成?我问是因为我想在我的应用程序中为多个小部件制作动画,我想找到最好的方法来做到这一点,而不必让太多的小部件相互依赖。

示例代码:

import sys
from PyQt4 import QtGui, QtCore


class AnimatedWidgets(QtGui.QWidget):
    def __init__(self):
        super(AnimatedWidgets, self).__init__()

        layout1 = QtGui.QVBoxLayout()
        self.setLayout(layout1)

        expanding_label = QtGui.QLabel("Expanding label!")
        expanding_label.setStyleSheet("border: 1px solid red")
        layout1.addWidget(expanding_label)

        self.file_model = QtGui.QFileSystemModel(self)
        sefl.file_model.setRootPath("C:/")
        self.browse_tree = QtGui.QTreeView()
        self.browse_tree.setModel(self.file_model)
        layout1.addWidget(self.browse_tree)

        shrink_tree_btn = QtGui.QPushButton("Shrink the tree")
        shrink_tree_btn.clicked.connect(self.shrink_tree)
        layout1.addWidget(shrink_tree_btn)

        #--

        self.tree_size_anim = QtCore.QPropertyAnimation(self.browse_tree, "size")
        self.tree_size_anim.setDuration(1000)
        self.tree_size_anim.setEasingCurve(QtCore.QEasingCurve.InOutQuart)
        self.tree_pos_anim = QtCore.QPropertyAnimation(self.browse_tree, "pos")
        self.tree_pos_anim.setDuration(1000)
        self.tree_pos_anim.setEasingCurve(QtCore.QEasingCurve.InOutQuart)
        self.tree_anim_out = QtCore.QParallelAnimationGroup()
        self.tree_anim_out.addAnimation(self.tree_size_anim)
        self.tree_anim_out.addAnimation(self.tree_pos_anim)

    def shrink_tree(self):
        self.tree_size_anim.setStartValue(self.browse_tree.size())
        self.tree_size_anim.setEndValue(QtCore.QSize(self.browse_tree.width(), 0))

        tree_rect = self.browse_tree.geometry()
        self.tree_pos_anim.setStartValue(tree_rect.topLeft())
        self.tree_pos_anim.setEndValue(QtCore.QPoint(tree_rect.left(), tree_rect.bottom()))

        self.tree_anim_out.start()
        self.tree_anim_out.finished.connect(self.browse_tree.hide)

def main():
    app = QtGui.QApplication(sys.argv)
    ex = AnimatedWidgets()

    ex.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

布局处理 geometry() of the widgets so that when wanting to change the pos property these are interfacing with their handles so it is very common that you get that type of behavior, a better option is to use a QVariantAnimation 以建立固定高度:

import sys
from PyQt4 import QtGui, QtCore


class AnimatedWidgets(QtGui.QWidget):
    def __init__(self):
        super(AnimatedWidgets, self).__init__()

        layout1 = QtGui.QVBoxLayout(self)

        expanding_label = QtGui.QLabel("Expanding label!")
        expanding_label.setStyleSheet("border: 1px solid red")
        layout1.addWidget(expanding_label)

        self.file_model = QtGui.QFileSystemModel(self)
        self.file_model.setRootPath(QtCore.QDir.rootPath())
        self.browse_tree = QtGui.QTreeView()
        self.browse_tree.setModel(self.file_model)
        layout1.addWidget(self.browse_tree)

        shrink_tree_btn = QtGui.QPushButton("Shrink the tree")
        shrink_tree_btn.clicked.connect(self.shrink_tree)
        layout1.addWidget(shrink_tree_btn)
        #--
        self.tree_anim = QtCore.QVariantAnimation(self)
        self.tree_anim.setDuration(1000)
        self.tree_anim.setEasingCurve(QtCore.QEasingCurve.InOutQuart)

    def shrink_tree(self):
        self.tree_anim.setStartValue(self.browse_tree.height())
        self.tree_anim.setEndValue(0)
        self.tree_anim.valueChanged.connect(self.on_valueChanged)
        self.tree_anim.start()

    def on_valueChanged(self, val):
        h, isValid = val.toInt()
        if isValid:
            self.browse_tree.setFixedHeight(h)

def main():
    app = QtGui.QApplication(sys.argv)
    ex = AnimatedWidgets()

    ex.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()