Este material fue extraido de StackOverflow y posteriormente adaptado.
Actualizaciones
- Corrección de dimensión en las transiciones del Stacked. [26/03/2021]
Indice
pip install PySide2
Primero tenemos que instanciar la clase Clase_EfectoSlider pasandole por parametro el stacked que se usara.
Esta clase solo se usara para uno, en caso de tener 2 o mas QStackedWidget, deberemos instaciarlo cuantos Stacked tengamos.
self.raizefestack = Clase_EfectoSlider(self.raiz.stackedWidget)indica si hay alguna transcicion ejecutandose.
self.ctrl_animacion = Falseself.raiz.btn1.clicked.connect(lambda :
self.raizefestack.transicion_stacked(index_final=0, indexSiguientes=[1,2]))
self.raiz.btn2.clicked.connect(lambda :
self.raizefestack.transicion_stacked(index_final=1, indexSiguientes=[2]))
self.raiz.btn3.clicked.connect(lambda :
self.raizefestack.transicion_stacked(index_final=2, indexSiguientes=[]))def transicion_stacked(self, index_final, indexSiguientes=[]):index_final: Index de pagina al que se dirije.
index_siguientes: Los index que siguen despues de el indicado del "0" le sigue [1,2], de "1" sigue [2] pero del "2" no le sigue nadie [] (esto para tener un efecto avance y retroceso).
obtener index actual
index_inicio = self.miStack.currentIndex()condicionamiento 1: no debe haber transciciones en ejecucion 2: el inicio y final no puede ser el mismo (index)
if(self.ctrl_animacion)or(index_final==index_inicio):
returnUna vez ingresada el control se activara
self.ctrl_animacion = TrueDeclaramos el index index_inicio y index_final en la clase, esto por que se utlizara en los controles de transición.
self.index_inicio = index_inicio
self.index_final = index_final'''
Direcionamiento de lienzo [↓] offsetx = 0; offsety = alto_stk [↑] offsetx = 0; offsety = -alto_stk [←] offsetx = ancho_stk; offsety = 0 [→] offsetx = -ancho_stk; offsety = 0
Para ello es sumamente importante obtener las dimenciones del widget
ancho_stk = self.miStack.width()
alto_stk = self.miStack.height()Avance y retroceso
Recapitulación de los parametros:
index_siguientes: Los index que siguen despues de el indicado del "0" le sigue [1,2], de "1" sigue [2] pero del "2" no le sigue nadie [] (esto para tener un efecto avance y retroceso).
if(self.index_inicio in indexSiguientes):
offsetx = -ancho_stk; offsety = 0
else:
offsetx = ancho_stk; offsety = 0Duración de efectos por milisegundos
velocidad_tansicion = 600En la transición podremos encontrar varios tipos en la documentacion de QEasingCurve
efecto_transicion = QEasingCurve.OutCubicSe establece el tamaño actual de Stacked al proximo widget, esto para evitar un bug visual de proporciones.
self.miStack.widget(self.index_final).resize(ancho_stk, alto_stk)Posicionamiento del widget
self.punto_actual = self.miStack.widget(self.index_inicio).pos()
self.punto_final = self.miStack.widget(self.index_final).pos()mostrar el siguiente widged en la transición
self.miStack.widget(self.index_final).show()obtener punto de referencia
offset = QPoint(offsetx, offsety)Crear un grupo de animacion para la transcicion de los widgets (esta se conectara con self.realizarAnimacion)
animacion_stack = QParallelAnimationGroup(self.miStack, finished=self.realizarAnimacion)Le agregamos la transcición de entrada y salida
animacion_inicio = QPropertyAnimation(
self.miStack.widget(self.index_inicio),b"pos",
duration=velocidad_tansicion, easingCurve=efecto_transicion,
startValue=self.punto_actual,
endValue=self.punto_final - offset)
animacion_final = QPropertyAnimation(
self.miStack.widget(self.index_final),b"pos",
duration=velocidad_tansicion, easingCurve=efecto_transicion,
startValue=self.punto_actual + offset,
endValue=self.punto_final)
animacion_stack.addAnimation(animacion_inicio)
animacion_stack.addAnimation(animacion_final)Por último iniciamos la ejecución
animacion_stack.start(QAbstractAnimation.DeleteWhenStopped)Previamente se meciono al self.realizarAnimacion cuya funcionalidad sera el cambio de index y los movimientos de sus widgets.
Tambien una vez finalizado los efectos, el self.ctrl_animacion se restablecera, tomando el valor de False
def realizarAnimacion(self):
self.miStack.setCurrentIndex(self.index_final) # asignar index
self.miStack.widget(self.index_inicio).hide()
self.miStack.widget(self.index_inicio).move(self.punto_actual)
# control de transicion (desactivado) /*/*/*/*/*/*/
self.ctrl_animacion = False