首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用动画将窗口小部件淡出到屏幕。

使用动画将窗口小部件淡出到屏幕。
EN

Stack Overflow用户
提问于 2022-11-22 12:47:55
回答 1查看 33关注 0票数 0

我希望实现一个按钮(已经有一个自定义类),当单击该按钮时,在切换到另一个布局(使用QStackedLayout实现)之前,会将现有屏幕上的所有小部件淡出。

我看过关于PySide6的不同文档和指南,介绍了如何动画化、渐进式/退出式,但似乎没有什么效果。不确定代码本身有什么问题,我已经完成了调试,动画类正在对小部件进行操作

我假设要使Widget淡出,我必须创建QGraphicsOpacityEffect,顶层小部件是父部件,然后添加QPropertyAnimation才能工作。

main.py

代码语言:javascript
复制
# Required Libraries for PySide6/Qt
from PySide6.QtWidgets import QWidget, QApplication, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QSizePolicy, QMainWindow, QSystemTrayIcon, QStackedLayout, QGraphicsOpacityEffect
from PySide6.QtGui import QIcon, QPixmap, QFont, QLinearGradient, QPainter, QColor
from PySide6.QtCore import Qt, QPointF, QSize, QVariantAnimation, QAbstractAnimation, QEasingCurve, QPropertyAnimation, QTimer

# For changing the taskbar icon
import ctypes
import platform

# For relative imports
import sys
sys.path.append('../classes')

# Classes and Different Windows
from classes.getStartedButton import getStartedButton

class window(QMainWindow):

    # Set up core components of window
    def __init__(self,h,w):
        # Gets primary parameters of the screen that the window will display in
        self.height = h
        self.width = w
        
        super().__init__()

        # Required to change taskbar icon
        if platform.system() == "Windows":
            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
                "com.random.appID")

        # Multiple screens will overlay each other
        self.layout = QStackedLayout()
        
        # Init splash screen - this is first
        self.splashScreen()
        
        # Function to init other screens
        self.initScreens()      
        
        # Must create main widget to hold the stacked layout, or another window will appear
        main_widget_holder = QWidget()
        main_widget_holder.setLayout(self.layout)
        self.setCentralWidget(main_widget_holder)
        

    def initScreens(self):
        
        apiScreen = QWidget()
        
        another_button = QPushButton("Test")
        another_layout = QVBoxLayout()
        another_layout.addWidget(another_button)
        apiScreen.setLayout(another_layout)
        self.layout.addWidget(apiScreen)

    # Window definition for splash screen
    def splashScreen(self):
        """Window that displays the splash screen
        """

        # Widget that holds all the widgets in the splash screen
        self.placeholder = QWidget()

        # Logo & Title Component
        logo = QLabel("")
        logo.setPixmap(QPixmap("image.png"))

        # Align logo on right side of the split
        logo.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        logo.setStyleSheet(
            "border-right:3px solid white;background-color: rgb(22,22,22);")

        title = QLabel("Another\nApp")
        title.setStyleSheet("padding-left:2px; font-size:36px")

        # Header to hold title and logo
        header_layout = QHBoxLayout()
        header_layout.addWidget(logo)
        header_layout.addWidget(title)

        header = QWidget()
        header.setStyleSheet("margin-bottom:20px")

        # Assign header_layout to the header widget
        header.setLayout(header_layout)

        # Button Component
        button = getStartedButton("Get Started  ")

        # Set max width of the button to cover both text and logo
        button.setMaximumWidth(self.placeholder.width())
        
        button.clicked.connect(self.transition_splash)

        # Vertical Layout from child widget components
        title_scrn = QVBoxLayout()
        title_scrn.addWidget(header)
        title_scrn.addWidget(button)

        # Define alignment to be vertically and horizontal aligned (Prevents button from appearing on the bottom of the app as well)
        title_scrn.setAlignment(Qt.AlignCenter)

        # Enlarge the default window size of 640*480 to something bigger (add 50px on all sides)
        self.placeholder.setLayout(title_scrn)
        self.placeholder.setObjectName("self.placeholder")

        self.placeholder.setMinimumSize(
            self.placeholder.width()+100, self.placeholder.height()+100)
        
        self.setCentralWidget(self.placeholder)

        # Grey/Black Background
        self.setStyleSheet(
            "QMainWindow{background-color: rgb(22,22,22);}QLabel{color:white} #button{padding:25px; border-radius:15px;background: qlineargradient(x1:0, y1:0,x2:1,y2:1,stop: 0 #00dbde, stop:1 #D600ff); border:1px solid white}")
        self.setMinimumSize(self.width/3*2,self.height/3*2)
       
        self.layout.addWidget(self.placeholder)
    def transition_splash(self):
        opacityEffect = QGraphicsOpacityEffect(self.placeholder)
        self.placeholder.setGraphicsEffect(opacityEffect)
        animationEffect = QPropertyAnimation(opacityEffect, b"opacity")
        animationEffect.setStartValue(1)
        animationEffect.setEndValue(0)
        animationEffect.setDuration(2500)
        animationEffect.start()
        timer = QTimer()
        timer.singleShot(2500,self.change_layout)
    
    def change_layout(self):
        self.layout.setCurrentIndex(1)

# Initialise program
if __name__ == "__main__":
    app = QApplication([])
    page = window(app.primaryScreen().size().height(),app.primaryScreen().size().width())
    page.show()
    sys.exit(app.exec())

button.py

代码语言:javascript
复制
# Required Libraries for PySide6/Qt
from PySide6.QtWidgets import QWidget, QApplication, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QSizePolicy, QMainWindow, QSystemTrayIcon, QStackedLayout, QGraphicsOpacityEffect
from PySide6.QtGui import QIcon, QPixmap, QFont, QLinearGradient, QPainter, QColor
from PySide6.QtCore import Qt, QPointF, QSize, QVariantAnimation, QAbstractAnimation, QEasingCurve

# Custom PushButton for splash screen
class getStartedButton(QPushButton):

    getStartedButtonColorStart = QColor(0, 219, 222)
    getStartedButtonColorInt = QColor(101, 118, 255)
    getStartedButtonColorEnd = QColor(214, 0, 255)

    def __init__(self, text):
        super().__init__()
        self.setText(text)

        # Setting ID so that it can be used in CSS
        self.setObjectName("button")
        self.setStyleSheet("font-size:24px")

        # Button Animation
        self.getStartedButtonAnimation = QVariantAnimation(
            self, startValue=0.42, endValue=0.98, duration=300)
        self.getStartedButtonAnimation.valueChanged.connect(
            self.animate_button)
        self.getStartedButtonAnimation.setEasingCurve(QEasingCurve.InOutCubic)
        

    def enterEvent(self, event):
        self.getStartedButtonAnimation.setDirection(QAbstractAnimation.Forward)
        self.getStartedButtonAnimation.start()
        # Suppression of event type error
        try:
            super().enterEvent(event)
        except TypeError:
            pass

    def leaveEvent(self, event):
        self.getStartedButtonAnimation.setDirection(
            QAbstractAnimation.Backward)
        self.getStartedButtonAnimation.start()
        # Suppression of event type error
        try:
            super().enterEvent(event)
        except TypeError:
            pass

    def animate_button(self, value):
        grad = "background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 {startColor}, stop:{value} {intermediateColor}, stop: 1.0 {stopColor});font-size:24px".format(
            startColor=self.getStartedButtonColorStart.name(), intermediateColor=self.getStartedButtonColorInt.name(), stopColor=self.getStartedButtonColorEnd.name(), value=value
        )
        self.setStyleSheet(grad)

对于上下文,我已经在SO和其他站点上查看了其他问题,例如

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-23 13:38:35

不确定代码有什么问题

QPropertyAnimation对象在有机会启动动画之前就被销毁了。你的问题已经解决了,here

要使其工作,您必须持久化对象:

代码语言:javascript
复制
def transition_splash(self):
    opacityEffect = QGraphicsOpacityEffect(self.placeholder)
    self.placeholder.setGraphicsEffect(opacityEffect)
    self.animationEffect = QPropertyAnimation(opacityEffect, b"opacity")
    self.animationEffect.setStartValue(1)
    self.animationEffect.setEndValue(0)
    self.animationEffect.setDuration(2500)
    self.animationEffect.start()

    # Use the finished signal instead of the QTimer
    self.animationEffect.finished.connect(self.change_layout)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74532883

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档