Search code examples
animationpyqtspyderpyqt6

Animated qtawesome icon does not repaint automatically


I have added an animated icon to a QAction which is in a QToolBar and a QActionGroup, but the animation is only re-drawn when the mouse enters / exits the widget area or when the window is resized. It would seem the underlying timer is continuing to function, as the rotation of the icon seems to be jumpy, but otherwise the correct speed when manually forcing the redraw with the mouse.

demo code and gif of behavior:

demonstration of only re-drawing icon with user interaction

import os
os.environ['QT_API'] = 'pyqt6' #for qtpy used by qtawesome

from PyQt6 import QtWidgets, QtCore, QtGui
import qtawesome as qta

class Main_App(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()

        toolbar = QtWidgets.QToolBar()
        toolbar.setOrientation(QtCore.Qt.Orientation.Vertical)
        action_group = QtGui.QActionGroup(toolbar)

        spin_widget = qta.IconWidget() #from qta demo
        spin_icon = qta.icon("mdi.loading", color="black", animation=qta.Spin(spin_widget))
        actionA = action_group.addAction(spin_icon, "A")
        toolbar.addAction(actionA)

        self.setCentralWidget(toolbar)

if __name__ == "__main__":
    qapp = QtWidgets.QApplication([])
    app = Main_App()
    app.show()
    qapp.exec()

How do I get it to continuously update? Is qtawesome simply not compatible with pyqt6 yet?

versions:

  • python 3.11.3
  • pyqt6 6.5.0
  • qtawesome 1.2.3

Solution

  • It turns out I was mixed up on the icon not being a widget itself, nor does an action contain a widget, and it is the widget associated with the action on the toolbar that must be passed to qta.Spin. I can access this value once the action has been added to the toolbar by toolbar.widgetForAction(actionA). The code then becomes:

    import os
    os.environ['QT_API'] = 'pyqt6' #for qtpy used by qtawesome
    
    from PyQt6 import QtWidgets, QtCore, QtGui
    import qtawesome as qta
    
    class Main_App(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
    
            toolbar = QtWidgets.QToolBar()
            toolbar.setOrientation(QtCore.Qt.Orientation.Vertical)
            action_group = QtGui.QActionGroup(toolbar)
    
            actionA = action_group.addAction("A") #create the action without an icon
            toolbar.addAction(actionA) #add the action to the toolbar before setting the icon because we need the widget created here
            
            spin_icon = qta.icon("mdi.loading", color="black", animation=qta.Spin(toolbar.widgetForAction(actionA)))
            actionA.setIcon(spin_icon)
    
            self.setCentralWidget(toolbar)
    
    if __name__ == "__main__":
        qapp = QtWidgets.QApplication([])
        app = Main_App()
        app.show()
        qapp.exec()