Qt изменить размер макета во время анимации свойства виджета - PullRequest
0 голосов
/ 30 мая 2018

У меня есть существующее приложение, которое я полирую, и я хочу добавить анимацию к нескольким виджетам.Анимация виджетов с помощью 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()

1 Ответ

0 голосов
/ 31 мая 2018

Макеты обрабатывают geometry() виджетов, так что при желании изменить свойство pos они взаимодействуют с их дескрипторами, поэтому очень часто вы получаетеДля этого типа поведения лучше использовать 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()
...