PyQt5 使用 QStackedWidget 实现轮播展示动画,但是鼠标移入却疯狂闪烁的解决办法
PyQt5 使用 QStackedWidget 实现轮播展示动画,但是鼠标移入却疯狂闪烁的解决办法
上篇说到,上篇见这里 我们可能会遇到,当把鼠标移动到 "下一页" 和 "上一页" 按钮,又或者是 Qlabel
标签页时,就会疯狂闪烁,于是在这里换另一种方案,解决这个问题
代码结构
本文基于上篇,上篇见这里 修改而来,全部代码在test_QStackedWidget_Animation.py
这一个文件中编码,步骤中有变动的地方会注释标注,无改动的不会重复显示出来,需要看完整代码的,可直接移步到末尾。
一. 修改代码
1. 修改DemoApp
中__init__
,启动透明度效果
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File : test_QStackedWidget_Animation.py
@ Author : yqbao
@ Version : V1.0.0
@ Description : 图片轮播动画
"""
class DemoApp(QWidget):
def __init__(self):
super().__init__()
... # 忽略
# 隐藏按钮和标签初始状态
# self.button_next.hide() # 注释这3行
# self.button_prev.hide()
# self.hide_current_page()
# 启用透明度效果
self.opacity_effect_prev = QGraphicsOpacityEffect(self.button_prev)
self.button_prev.setGraphicsEffect(self.opacity_effect_prev)
self.opacity_effect_prev.setOpacity(0)
self.opacity_effect_next = QGraphicsOpacityEffect(self.button_next)
self.button_next.setGraphicsEffect(self.opacity_effect_next)
self.opacity_effect_next.setOpacity(0)
# 设置透明背景
self.button_prev.setAttribute(Qt.WA_TranslucentBackground)
self.button_next.setAttribute(Qt.WA_TranslucentBackground)
self.hide_current_page()
2. 修改DemoApp
中hide_current_page
方法
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File : test_QStackedWidget_Animation.py
@ Author : yqbao
@ Version : V1.0.0
@ Description : 图片轮播动画
"""
def hide_current_page(self):
"""隐藏标签页"""
# for label in self.page_labels:
# label.hide()
for label in self.page_labels:
self.opacity_effect_next = QGraphicsOpacityEffect(label)
label.setGraphicsEffect(self.opacity_effect_next)
self.opacity_effect_next.setOpacity(0)
3. 在DemoApp
中增加两个新方法,使用属性动画,修改透明度
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File : test_QStackedWidget_Animation.py
@ Author : yqbao
@ Version : V1.0.0
@ Description : 图片轮播动画
"""
@staticmethod
def fade_in(widget):
opacity_effect = widget.graphicsEffect()
animation = QPropertyAnimation(opacity_effect, b"opacity")
animation.setDuration(200)
animation.setStartValue(1)
animation.setEndValue(0)
animation.start()
@staticmethod
def fade_out(widget):
opacity_effect = widget.graphicsEffect()
animation = QPropertyAnimation(opacity_effect, b"opacity")
animation.setDuration(200)
animation.setStartValue(0)
animation.setEndValue(1)
animation.start()
4. 修改DemoApp
中eventFilter
方法
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File : test_QStackedWidget_Animation.py
@ Author : yqbao
@ Version : V1.0.0
@ Description : 图片轮播动画
"""
def eventFilter(self, obj, event):
"""事件过滤,鼠标移入与移出"""
if event.type() == QEvent.Enter and obj is self:
self.fade_in(self.button_next)
self.fade_in(self.button_prev)
for label in self.page_labels:
self.fade_in(label)
elif event.type() == QEvent.Leave and obj is self:
self.fade_out(self.button_next)
self.fade_out(self.button_prev)
for label in self.page_labels:
self.fade_out(label)
return super().eventFilter(obj, event)
二. DemoApp
完整代码
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File : test_QStackedWidget_Animation.py
@ Author : yqbao
@ Version : V1.0.0
@ Description : 图片轮播动画
"""
from PyQt5.QtWidgets import QApplication, QWidget, QStackedWidget, QVBoxLayout, QPushButton, QLabel, \
QGraphicsOpacityEffect
from PyQt5.QtCore import QPropertyAnimation, QEasingCurve, QRect, QEvent, Qt, QTimer
class DemoApp(QWidget, Ui_DemoApp):
def __init__(self):
super().__init__()
self.setupUi(self)
# 连接按钮事件
self.button_next.clicked.connect(self.next_page)
self.button_prev.clicked.connect(self.prev_page)
# 启用透明度效果
self.opacity_effect_prev = QGraphicsOpacityEffect(self.button_prev)
self.button_prev.setGraphicsEffect(self.opacity_effect_prev)
self.opacity_effect_prev.setOpacity(0)
self.opacity_effect_next = QGraphicsOpacityEffect(self.button_next)
self.button_next.setGraphicsEffect(self.opacity_effect_next)
self.opacity_effect_next.setOpacity(0)
# 设置透明背景
self.button_prev.setAttribute(Qt.WA_TranslucentBackground)
self.button_next.setAttribute(Qt.WA_TranslucentBackground)
self.hide_current_page()
# 高亮当前页码
self.highlight_current_page()
# 定时器设置
self.timer = QTimer(self)
self.timer.timeout.connect(self.auto_next_page) # 自动轮播
self.timer.start(3000) # 每3秒切换一次
# 安装事件过滤器到窗口
self.installEventFilter(self)
def auto_next_page(self):
"""自动切换到下一页"""
self.next_page()
def reset_timer(self):
"""重置定时器,以保持自动轮播"""
self.timer.start(3000)
def hide_current_page(self):
"""隐藏标签页"""
for label in self.page_labels:
self.opacity_effect_next = QGraphicsOpacityEffect(label)
label.setGraphicsEffect(self.opacity_effect_next)
self.opacity_effect_next.setOpacity(0)
def set_geometry_current_page(self):
"""设置标签页位置"""
for i, label in enumerate(self.page_labels):
label.setGeometry(self.width() // 2 + i * 15 - 30, self.height() - 45, 60, 30)
@staticmethod
def fade_in(widget):
opacity_effect = widget.graphicsEffect()
animation = QPropertyAnimation(opacity_effect, b"opacity")
animation.setDuration(200)
animation.setStartValue(1)
animation.setEndValue(0)
animation.start()
@staticmethod
def fade_out(widget):
opacity_effect = widget.graphicsEffect()
animation = QPropertyAnimation(opacity_effect, b"opacity")
animation.setDuration(200)
animation.setStartValue(0)
animation.setEndValue(1)
animation.start()
def eventFilter(self, obj, event):
"""事件过滤,鼠标移入与移出"""
if event.type() == QEvent.Enter and obj is self:
self.fade_in(self.button_next)
self.fade_in(self.button_prev)
for label in self.page_labels:
self.fade_in(label)
elif event.type() == QEvent.Leave and obj is self:
self.fade_out(self.button_next)
self.fade_out(self.button_prev)
for label in self.page_labels:
self.fade_out(label)
return super().eventFilter(obj, event)
def highlight_current_page(self, index=0):
"""更新标签样式"""
for i, label in enumerate(self.page_labels):
if i == index:
label.setStyleSheet("color: black; font-weight: bold;") # 高亮当前页码
else:
label.setStyleSheet("color: gray;") # 暗淡其他页码
def next_page(self):
"""下一页"""
current_index = self.stacked_widget.currentIndex()
next_index = (current_index + 1) % self.stacked_widget.count()
self.stacked_widget.set_current_index_with_animation(next_index, direction='left')
self.highlight_current_page(next_index)
self.reset_timer()
def prev_page(self):
"""上一页"""
current_index = self.stacked_widget.currentIndex()
prev_index = (current_index - 1) % self.stacked_widget.count()
self.stacked_widget.set_current_index_with_animation(prev_index, direction='right')
self.highlight_current_page(prev_index)
self.reset_timer()
def resizeEvent(self, event):
"""更新按钮位置"""
super().resizeEvent(event)
self.button_next.setGeometry(self.width() - 80, self.height() // 2 - 15, 60, 30)
self.button_prev.setGeometry(20, self.height() // 2 - 15, 60, 30)
self.set_geometry_current_page()
本文来自博客园作者:星尘的博客,转载请注明出处:https://www.cnblogs.com/yqbaowo/p/18422153