Important: Please read the Qt Code of Conduct -

Mac OS - repainting parented widget performance seem to depend on ancestors chain.

  • Hi,

    Using Qt 5.9.1 on Windows 10 and Mac OS Sierra.
    In my application there is a MyVideo QWidget based type that has QTimer member which periodically (1/30 sec) fires ::timeout signal triggering MyVideo::animateFrame that:

    1. stops the timer
    2. draws something on QImage
    3. calls ::repaint method which in turn is triggering ::paintEvent.
    4. starts the timer again

    In MyVideo ::paintEvent method QPainter instance is created and QImage is drawn on screen via ::drawImage(QPoint, QImage).
    This simple setup works just fine on Windows.
    On Mac visual redraw rate decreases as application window grows in size (the animation size stays the same) and increases when application window becomes smaller.

    I did many attempts to figure out why experimenting with various widget attributes, drawing api and etc.
    MyVideo::animateFrame execution time (including ::repaint call) is just few msec.
    Finally I splitted my MyVideo type into two types.
    I removed paintEvent implementation from MyVideo and moved it to new MyVideoOutput type.
    The only thing MyVideoOutput does is to draw that image that is defined in MyVideo (technically MyVideoOutput is a friend of MyVideo).
    Lastly, MyVideoOutput has no parent widget.

    And now, animation works just fine with no regard to application/ancestor dimensions.
    So what I have is MyVideo instance inside layout with all functionality inside and MyVideoOutput outside of layout, actually a top level window, doing nothing except drawImage.

    This entire setup although working is not suitable for my needs. The animation must be embedded inside application layout.

    Does anyone has an idea how to make this work without introducing top level window?
    Thanks a lot!

  • Hi! You can get 2D hardware acceleration by using QOpenGLWidget as the base class for your MyVideo widget. See 2D Painting Example.

  • Hi, Wieland

    Yes, meanwhile I discovered that QOpenGLWidget can almost solve my situation like your correct suggestion.
    It is definitely makes performance much much better and consistent.

    I say almost, is because I notice some flicking for example when I hover in or out some button.
    Also a couple of QOpenGLWidget based widgets that overlap MyVideo on screen (which are used as layers on top of playing video, they draw themselves repeatedly e.g. when user moves the mouse)
    get black background and so far I can't make it transparent.
    Tried the suggestion here:
    But it doesn't work , it seems that example is relevant for top level windows only.

    Have any idea why is the flickering on hovers and how to make QOpenGLWidget widgets with transparent background ?


  • It is hard to believe that Mac drawing system chokes from such simple drawing operations like drawImage or a few drawRect/fillRect/drawText calls.
    It seems unbelievable:(, it is not that I'm drawing hundredths of complex shapes...
    QOpenGLWidget usage as a workaround for me.

  • After some debugging the QOpenGLWidget flickering on input hover I now have some more insight.
    It seems it is related to styling transition that element goes through either from qss code or regular code.

    I want to share the solution I'm using now to stop flickering.
    Just connect your instance in following way:

    connect(QOpenGLWidget * , &QOpenGLWidget::frameSwapped, QOpenGLWidget *, QOverload<>::of(&QOpenGLWidget::update));

    It seems that there are occasions where ::paintEvent is not called when it should be.

Log in to reply