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. 修改DemoApphide_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. 修改DemoAppeventFilter方法

#!/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)

image

二. 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()

本文章的原文地址
GitHub主页

posted @ 2024-09-20 13:29  星尘的博客  阅读(18)  评论(0编辑  收藏  举报