我希望实现一个按钮(已经有一个自定义类),当单击该按钮时,在切换到另一个布局(使用QStackedLayout实现)之前,会将现有屏幕上的所有小部件淡出。
我看过关于PySide6的不同文档和指南,介绍了如何动画化、渐进式/退出式,但似乎没有什么效果。不确定代码本身有什么问题,我已经完成了调试,动画类正在对小部件进行操作
我假设要使Widget淡出,我必须创建QGraphicsOpacityEffect,顶层小部件是父部件,然后添加QPropertyAnimation才能工作。
main.py
# 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
# 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和其他站点上查看了其他问题,例如
发布于 2022-11-23 13:38:35
不确定代码有什么问题
QPropertyAnimation对象在有机会启动动画之前就被销毁了。你的问题已经解决了,here。
要使其工作,您必须持久化对象:
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)https://stackoverflow.com/questions/74532883
复制相似问题