Python qt-stackwidget动画;上一个小部件消失

Python qt-stackwidget动画;上一个小部件消失,python,qt,animation,pyqt4,Python,Qt,Animation,Pyqt4,我正在尝试使用Qt中的动画工具(QPropertyAnimation)为QStackedWidget的更改设置动画。不幸的是,有两个问题: 上一个小部件消失(不设置动画) 下一个小部件在可见之前不会更改位置 有什么想法吗 Python 2.7、PyQt4、Win 7、Win 10、OpenSuse 完整示例 导入系统 从PyQt4导入QtCore、QtGui 颜色列表=[‘红色’、‘蓝色’、‘绿色’] 动画速度=2000 def make_回调(函数,*参数): ''' Helper函数以确

我正在尝试使用Qt中的动画工具(
QPropertyAnimation
)为
QStackedWidget
的更改设置动画。不幸的是,有两个问题:

  • 上一个小部件消失(不设置动画)
  • 下一个小部件在可见之前不会更改位置
  • 有什么想法吗

    Python 2.7、PyQt4、Win 7、Win 10、OpenSuse

    完整示例


    导入系统 从PyQt4导入QtCore、QtGui 颜色列表=[‘红色’、‘蓝色’、‘绿色’] 动画速度=2000 def make_回调(函数,*参数): ''' Helper函数以确保lambda函数被缓存且不会丢失。 ''' 返回lambda:func(*param) 类应用程序(QtGui.QMainWindow): 定义初始化(self、app、parent=None): QtGui.QMainWindow.\uuuuu init\uuuuu(self,parent) #对qapp实例的引用 self.app=app self.animating=False self.stack_动画=无 自我调整大小(QtCore.QSize(500200)) #小部件 self.mainwidget=QtGui.QWidget() self.setCentralWidget(self.mainwidget) self.listwidget=QtGui.QListWidget() self.listwidget.addItems(颜色列表) self.listwidget.itemSelectionChanged.connect(self.change\u颜色) self.stackedwidget=QtGui.QStackedWidget() 对于颜色列表中的颜色: widget=QtGui.QWidget() setStyleSheet('QWidget{' '背景色:'+color+';' '}') widget.setObjectName(颜色) self.stackedwidget.addWidget(小部件) #布局 self.hlayout=QtGui.QHBoxLayout(self.mainwidget) self.mainwidget.setLayout(self.hlayout) self.hlayout.addWidget(self.listwidget) self.hlayout.addWidget(self.stackedwidget) def更改颜色(自身): new_color=str(self.listwidget.currentItem().text()) old_color=str(self.stackedwidget.currentWidget().objectName()) old_index=self.stackedwidget.currentIndex() 新索引=0 对于范围内的i(self.stackedwidget.count()): widget=self.stackedwidget.widget(i) 如果new_color==str(widget.objectName()): 新指数=i 打破 打印('更改自:'、旧颜色、旧索引、, “收件人:”,新颜色,新索引) 设置自身动画(旧索引、新索引) def动画(自、自、至、方向='垂直'): “”“动画更改qstackedwidget”“” #检查是否已设置动画 如果self.animating和self.stack_动画不是None: self.stack_animation.stop() from\u widget=self.stackedwidget.widget(from\u) to_widget=self.stackedwidget.widget(to) #从几何中获取 宽度=来自_widget.frameGeometry().width() 高度=来自_widget.frameGeometry().height() #抵消 #自下而上 如果方向=='垂直',且从\<到: offsetx=0 偏移量=高度 #自上而下 elif方向=='垂直'和从\>到: offsetx=0 偏移量=-高度 elif方向==“水平”和从<<到: 偏移量x=宽度 offsety=0 elif方向=='水平'和从\>到: 偏移量x=-width offsety=0 其他: 返回 #移动到widget并显示 #设置下一个小部件的几何图形 to_widget.setGeometry(0+offsetx、0+offsety、宽度、高度) to_widget.show() to_widget.lower() 到_widget.raise_() #生动活泼 #来自小部件 animnow=QtCore.QPropertyAnimation(来自_小部件“pos”) 设置持续时间(动画速度) animnow.setEasingCurve(QtCore.QEasingCurve.InOutQuint) animnow.setStartValue( QtCore.QPoint(0, 0)) animnow.setEndValue( QtCore.QPoint(0-偏移量, 0-偏移量) #小部件 animnext=QtCore.QPropertyAnimation(到_小部件,“pos”) 设置持续时间(动画速度) animnext.setEasingCurve(QtCore.QEasingCurve.InOutQuint) animnext.setStartValue( QtCore.QPoint(0+offsetx, 0+偏移量) animnext.setEndValue( QtCore.QPoint(0, 0)) #动画组 self.stack_animation=QtCore.qParallelLanimationGroup() self.stack\u animation.addAnimation(animnow) self.stack\u animation.addAnimation(animnext) self.stack\u animation.finished.connect( 使\u回调(self.animate\u堆叠\u小部件\u完成, 从(到) ) self.stack\u animation.stateChanged.connect( 使\u回调(self.animate\u堆叠\u小部件\u完成, 从(到) ) self.animating=True self.stack_animation.start() def动画_堆叠_小部件_完成(自、自、至): “”“动画后清理”“” self.stackedwidget.setCurrentIndex(到) from\u widget=self.stackedwidget.widget(from\u) 来自_widget.hide() 从_widget.move(0,0) self.animating=False 如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu': qapp=QtGui.QApplication(sys.argv) app=app(qapp) app.show() qapp.exec() qapp.deleteLater() sys.exit()
    动画开始时调用
    QtCore.QParallelAnimationGroup.stateChanged
    信号,因此它调用了我的
    动画堆叠的\u小部件\u finished
    方法并将
    隐藏在\u小部件中

    仍然需要捕获此事件以在动画完成时处理。只需添加一个
    if
    语句来检查
    qParallelLanimationGroup
    的状态

    更换<代码
    import sys
    from PyQt4 import QtCore, QtGui
    
    COLOR_LIST = ['red','blue','green']
    ANIMATION_SPEED = 2000
    
    def make_callback(func, *param):
        '''
        Helper function to make sure lambda functions are cached and not lost.
        '''
        return lambda: func(*param)
    
    class App(QtGui.QMainWindow):
    
        def __init__(self, app, parent=None):
            QtGui.QMainWindow.__init__(self, parent)
    
            # reference to qapp instance
            self.app = app
    
            self.animating = False
            self.stack_animation = None
    
            self.resize(QtCore.QSize(500,200))
    
            # widgets
            self.mainwidget = QtGui.QWidget()
            self.setCentralWidget(self.mainwidget)
    
            self.listwidget = QtGui.QListWidget()
            self.listwidget.addItems(COLOR_LIST)
            self.listwidget.itemSelectionChanged.connect(self.change_color)
    
            self.stackedwidget = QtGui.QStackedWidget()
    
            for color in COLOR_LIST:
                widget = QtGui.QWidget()
                widget.setStyleSheet('QWidget{'
                                     '  background-color: '+color+';'
                                     '}')
                widget.setObjectName(color)
                self.stackedwidget.addWidget(widget)
    
            # layouts
            self.hlayout = QtGui.QHBoxLayout(self.mainwidget)
            self.mainwidget.setLayout(self.hlayout)
    
            self.hlayout.addWidget(self.listwidget)
            self.hlayout.addWidget(self.stackedwidget)
    
        def change_color(self):
    
            new_color = str(self.listwidget.currentItem().text())
            old_color = str(self.stackedwidget.currentWidget().objectName())
    
            old_index = self.stackedwidget.currentIndex()
            new_index = 0
            for i in range(self.stackedwidget.count()):
                    widget = self.stackedwidget.widget(i)
                    if new_color == str(widget.objectName()):
                        new_index = i
                        break
    
            print('Changing from:', old_color, old_index,
                  'To:', new_color, new_index)
    
            self.animate(old_index, new_index)
    
        def animate(self, from_, to, direction='vertical'):
            """ animate changing of qstackedwidget """
    
            # check to see if already animating
            if self.animating and self.stack_animation is not None:
                self.stack_animation.stop()
    
            from_widget = self.stackedwidget.widget(from_)
            to_widget = self.stackedwidget.widget(to)
    
            # get from geometry
            width = from_widget.frameGeometry().width()
            height = from_widget.frameGeometry().height()
    
            # offset
            # bottom to top
            if direction == 'vertical' and from_ < to:
                offsetx = 0
                offsety = height
            # top to bottom
            elif direction == 'vertical' and from_ > to:
                offsetx = 0
                offsety = -height
            elif direction == 'horizontal' and from_ < to:
                offsetx = width
                offsety = 0
            elif direction == 'horizontal' and from_ > to:
                offsetx = -width
                offsety = 0
            else:
                return
    
            # move to widget and show
            # set the geometry of the next widget
            to_widget.setGeometry(0 + offsetx, 0 + offsety, width, height)
    
    
            to_widget.show()
            to_widget.lower()
            to_widget.raise_()
    
            # animate
            # from widget
            animnow = QtCore.QPropertyAnimation(from_widget, "pos")
            animnow.setDuration(ANIMATION_SPEED)
            animnow.setEasingCurve(QtCore.QEasingCurve.InOutQuint)
            animnow.setStartValue(
                QtCore.QPoint(0,
                              0))
            animnow.setEndValue(
                QtCore.QPoint(0 - offsetx,
                              0 - offsety))
    
            # to widget
            animnext = QtCore.QPropertyAnimation(to_widget, "pos")
            animnext.setDuration(ANIMATION_SPEED)
            animnext.setEasingCurve(QtCore.QEasingCurve.InOutQuint)
            animnext.setStartValue(
                QtCore.QPoint(0 + offsetx,
                              0 + offsety))
            animnext.setEndValue(
                QtCore.QPoint(0,
                              0))
    
            # animation group
            self.stack_animation = QtCore.QParallelAnimationGroup()
            self.stack_animation.addAnimation(animnow)
            self.stack_animation.addAnimation(animnext)
            self.stack_animation.finished.connect(
                make_callback(self.animate_stacked_widget_finished,
                              from_, to)
                )
            self.stack_animation.stateChanged.connect(
                make_callback(self.animate_stacked_widget_finished,
                              from_, to)
                )
    
            self.animating = True
            self.stack_animation.start()
    
        def animate_stacked_widget_finished(self, from_, to):
            """ cleanup after animation """
            self.stackedwidget.setCurrentIndex(to)
            from_widget = self.stackedwidget.widget(from_)
            from_widget.hide()
            from_widget.move(0, 0)
            self.animating = False
    
    
    if __name__ == '__main__':
        qapp = QtGui.QApplication(sys.argv)
    
        app = App(qapp)
        app.show()
        qapp.exec_()
        qapp.deleteLater()
        sys.exit()
    
    def animate_stacked_widget_finished(self, from_, to):
        """ cleanup after animation """
        if self.stack_animation.state() == QtCore.QAbstractAnimation.Stopped:
            self.stackedwidget.setCurrentIndex(to)
            from_widget = self.stackedwidget.widget(from_)
            from_widget.hide()
            from_widget.move(0, 0)
            self.animating = False