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 = False
self.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):
return
Una vez ingresada el control se activara
self.ctrl_animacion = True
Declaramos 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 = 0
Duración de efectos por milisegundos
velocidad_tansicion = 600
En la transición podremos encontrar varios tipos en la documentacion de QEasingCurve
efecto_transicion = QEasingCurve.OutCubic
Se 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