Animating the scale of a QDialog
-
I'm looking for ways to animate the scale of a QDialog to create a smooth animated popup.
Qt widgets don't have a scale property that you can animate, so I tried using a
QGraphicsView()
and wrapped aQDialog
in aQGraphicsProxyWidget()
.The problem then becomes that the
QGraphicsView
doesn't have a.exec()
method that would force theQDialog
to be interacted with before proceeding.Maybe someone knows a workaround or better yet another approach how I could animate the scale(not the height and width) of the
QDialog
This is how it looks:
Full code, you can replace
uic.loadUi("Error.ui", self)
with your own.ui
file:from PyQt6.QtWidgets import (QApplication, QDialog, QStyleFactory, QGraphicsView, QGraphicsScene, QGraphicsProxyWidget) from PyQt6.QtCore import Qt, QPropertyAnimation, QEasingCurve from PyQt6 import uic import sys import os class ExpandingDialog(QDialog): def __init__(self): super().__init__() # Load your own uic.loadUi("Error.ui", self) self.setWindowFlag(Qt.WindowType.FramelessWindowHint) self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) # Create a Graphics View and Scene to enable scaling animation self.scene = QGraphicsScene() self.view = QGraphicsView(self.scene) self.view.setWindowFlags(Qt.WindowType.FramelessWindowHint) self.view.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) self.view.setStyleSheet("background: transparent; border: none;") self.view.setFixedSize(self.width(), self.height()) # Wrap the Dialog inside a QGraphicsProxyWidget self.proxy_widget = QGraphicsProxyWidget() self.proxy_widget.setWidget(self) self.scene.addItem(self.proxy_widget) def showEvent(self, event): self.start_animation() self.view.show() # self.exec() def start_animation(self): # Scale Animation self.scale_animation = QPropertyAnimation(self.proxy_widget, b"scale") self.scale_animation.setDuration(600) self.scale_animation.setStartValue(0.0) self.scale_animation.setEndValue(1.0) self.scale_animation.setEasingCurve(QEasingCurve.Type.OutCubic) # Opacity Animation self.opacity_animation = QPropertyAnimation(self.proxy_widget, b"opacity") self.opacity_animation.setDuration(300) self.opacity_animation.setStartValue(0.0) self.opacity_animation.setEndValue(1.0) # Start Animations self.scale_animation.start() self.opacity_animation.start() if __name__ == "__main__": os.environ['QT_ENABLE_HIGHDPI_SCALING'] = '0' os.environ['QT_FONT_DPI'] = '120' app = QApplication(sys.argv) app.setStyle(QStyleFactory.create('windowsvista')) dialog = ExpandingDialog() dialog.exec()
-
I'm looking for ways to animate the scale of a QDialog to create a smooth animated popup.
Qt widgets don't have a scale property that you can animate, so I tried using a
QGraphicsView()
and wrapped aQDialog
in aQGraphicsProxyWidget()
.The problem then becomes that the
QGraphicsView
doesn't have a.exec()
method that would force theQDialog
to be interacted with before proceeding.Maybe someone knows a workaround or better yet another approach how I could animate the scale(not the height and width) of the
QDialog
This is how it looks:
Full code, you can replace
uic.loadUi("Error.ui", self)
with your own.ui
file:from PyQt6.QtWidgets import (QApplication, QDialog, QStyleFactory, QGraphicsView, QGraphicsScene, QGraphicsProxyWidget) from PyQt6.QtCore import Qt, QPropertyAnimation, QEasingCurve from PyQt6 import uic import sys import os class ExpandingDialog(QDialog): def __init__(self): super().__init__() # Load your own uic.loadUi("Error.ui", self) self.setWindowFlag(Qt.WindowType.FramelessWindowHint) self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) # Create a Graphics View and Scene to enable scaling animation self.scene = QGraphicsScene() self.view = QGraphicsView(self.scene) self.view.setWindowFlags(Qt.WindowType.FramelessWindowHint) self.view.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) self.view.setStyleSheet("background: transparent; border: none;") self.view.setFixedSize(self.width(), self.height()) # Wrap the Dialog inside a QGraphicsProxyWidget self.proxy_widget = QGraphicsProxyWidget() self.proxy_widget.setWidget(self) self.scene.addItem(self.proxy_widget) def showEvent(self, event): self.start_animation() self.view.show() # self.exec() def start_animation(self): # Scale Animation self.scale_animation = QPropertyAnimation(self.proxy_widget, b"scale") self.scale_animation.setDuration(600) self.scale_animation.setStartValue(0.0) self.scale_animation.setEndValue(1.0) self.scale_animation.setEasingCurve(QEasingCurve.Type.OutCubic) # Opacity Animation self.opacity_animation = QPropertyAnimation(self.proxy_widget, b"opacity") self.opacity_animation.setDuration(300) self.opacity_animation.setStartValue(0.0) self.opacity_animation.setEndValue(1.0) # Start Animations self.scale_animation.start() self.opacity_animation.start() if __name__ == "__main__": os.environ['QT_ENABLE_HIGHDPI_SCALING'] = '0' os.environ['QT_FONT_DPI'] = '120' app = QApplication(sys.argv) app.setStyle(QStyleFactory.create('windowsvista')) dialog = ExpandingDialog() dialog.exec()
-
What if you pick the
geometry
property instead of scale? I don't think you need theQGraphicsView
for that -
What if you pick the
geometry
property instead of scale? I don't think you need theQGraphicsView
for that@Pl45m4 I actually recently learned that you can basically overlay any widget on top of widgets in a layout, so I made something better. As an alternative for animating the scale, I guess you can just take a snapshot of your widget, and just animate the scale in After Effects or something, and show the animation first and than the dialog itself.