3

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

假设我有一个 QVBoxLayout,其中包含三个小部件:一个应该扩展到所有可用空间的标签、一个树视图和一个按钮。当我单击按钮时,我希望树折叠并且标签接管它的空间。下面是代码中的示例,正​​如您所看到的,当树对其大小进行动画处理时,什么也没有发生,然后当我在动画结束时将其隐藏时,标签会弹出以填充现在的空白空间。因此,在动画期间,布局似乎并不“知道”树正在调整大小。我想要发生的是,随着树的缩小,标签会扩大以填充它。

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

示例代码:

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()
4

1 回答 1

1

布局处理geometry()小部件的 ,因此当想要更改pos属性时,它们与它们的句柄交互,因此您得到这种行为是很常见的,更好的选择是使用 aQVariantAnimation来建立固定高度:

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()
于 2018-05-30T22:36:04.427 回答