What is the best way to display an animated icon in a QTableView?

qstyleditemdelegate
qtableview example
qtableview example python
qabstracttablemodel
qabstracttablemodel example
qitemdelegate
pyqt5 qtableview example
qtableview pyqt5

I've been struggling with this for some times now, and I can't seem to find the right way to do this.

What I would like is the ability to use an animated icon as a decoration for some of my items (typically to show that some processing is occuring for this particular item). I have a custom table model, that I display in a QTableView.

My first idea was to create a custom delegate that would take care of displaying the animation. When passed a QMovie for the decoration role, the delegate would connect to the QMovie in order to update the display every time a new frame is available (see code below). However, the painter does not seem to remain valid after the call to the delegate's paint method (I get an error when calling the painter's save method, probably because the pointer no longer points to valid memory).

Another solution would be to emit the dataChanged signal of the item every time a new frame is available, but 1) that would induce many unnecessary overhead, since the data is not really changed; 2) it does not seem really clean to handle the movie at the model level: it should be the responsibility of the display tier (QTableView or the delegate) to handle the display of new frames.

Does anyone know a clean (and preferably efficient) way to display animation in Qt views?


For those interested, here is the code of the delegate I developped (which does not work at the moment).

// Class that paints movie frames every time they change, using the painter
// and style options provided
class MoviePainter : public QObject
{
    Q_OBJECT

  public: // member functions
    MoviePainter( QMovie * movie, 
                  QPainter * painter, 
                  const QStyleOptionViewItem & option );

  public slots:
    void paint( ) const;

  private: // member variables
    QMovie               * movie_;
    QPainter             * painter_;
    QStyleOptionViewItem   option_;
};


MoviePainter::MoviePainter( QMovie * movie,
                            QPainter * painter,
                            const QStyleOptionViewItem & option )
  : movie_( movie ), painter_( painter ), option_( option )
{
    connect( movie, SIGNAL( frameChanged( int ) ),
             this,  SLOT( paint( ) ) );
}

void MoviePainter::paint( ) const
{
    const QPixmap & pixmap = movie_->currentPixmap();

    painter_->save();
    painter_->drawPixmap( option_.rect, pixmap );
    painter_->restore();
}

//-------------------------------------------------

//Custom delegate for handling animated decorations.
class MovieDelegate : public QStyledItemDelegate
{
    Q_OBJECT

  public: // member functions
    MovieDelegate( QObject * parent = 0 );
    ~MovieDelegate( );

    void paint( QPainter * painter, 
                const QStyleOptionViewItem & option, 
                const QModelIndex & index ) const;

  private: // member functions
    QMovie * qVariantToPointerToQMovie( const QVariant & variant ) const;

  private: // member variables
    mutable std::map< QModelIndex, detail::MoviePainter * > map_;
};

MovieDelegate::MovieDelegate( QObject * parent )
  : QStyledItemDelegate( parent )
{
}

MovieDelegate::~MovieDelegate( )
{
    typedef  std::map< QModelIndex, detail::MoviePainter * > mapType;

          mapType::iterator it = map_.begin();
    const mapType::iterator end = map_.end();

    for ( ; it != end ; ++it )
    {
        delete it->second;
    }
}

void MovieDelegate::paint( QPainter * painter, 
                           const QStyleOptionViewItem & option, 
                           const QModelIndex & index ) const
{
    QStyledItemDelegate::paint( painter, option, index );

    const QVariant & data = index.data( Qt::DecorationRole );

    QMovie * movie = qVariantToPointerToQMovie( data );

    // Search index in map
    typedef std::map< QModelIndex, detail::MoviePainter * > mapType;

    mapType::iterator it = map_.find( index );

    // if the variant is not a movie
    if ( ! movie )
    {
        // remove index from the map (if needed)
        if ( it != map_.end() )
        {
            delete it->second;
            map_.erase( it );
        }

        return;
    }

    // create new painter for the given index (if needed)
    if ( it == map_.end() )
    {
        map_.insert( mapType::value_type( 
                index, new detail::MoviePainter( movie, painter, option ) ) );
    }
}

QMovie * MovieDelegate::qVariantToPointerToQMovie( const QVariant & variant ) const
{
    if ( ! variant.canConvert< QMovie * >() ) return NULL;

    return variant.value< QMovie * >();
}

The best solution is to use QSvgRenderer within delegate.

It's very easy to implement and unlike gif, SVG is lightweight and supports transparency.

    TableViewDelegate::TableViewDelegate(TableView* view, QObject* parent)
    : QStyledItemDelegate(parent), m_view(view)
{
    svg_renderer = new QSvgRenderer(QString{ ":/res/img/spinning_icon.svg" }, m_view);

    connect(svg_renderer, &QSvgRenderer::repaintNeeded,
        [this] {
        m_view->viewport()->update();
    });
}


void TableViewDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
    const QModelIndex& index) const
{
    QStyleOptionViewItem opt{ option };
    initStyleOption(&opt, index);

    if (index.column() == 0) {
        if (condition)
        {
            // transform bounds, otherwise fills the whole cell
            auto bounds = opt.rect;
            bounds.setWidth(28);
            bounds.moveTo(opt.rect.center().x() - bounds.width() / 2,
                opt.rect.center().y() - bounds.height() / 2);

            svg_renderer->render(painter, bounds);
        }
    }

    QStyledItemDelegate::paint(painter, opt, index);
}

Here's a nice website where you can generate your own spinning icon and export in SVG.

c++ – What is the best way to display an animated icon in a , c++ – What is the best way to display an animated icon in a QTableView? for some times now, and I can't seem to find the right way to do this. Browse other questions tagged qt combobox pyqt qtableview or ask your own question. What is the best way to display an animated icon in a QTableView? 4.

For the record, I ended up using QAbstractItemView::setIndexWidget from inside the paint method of my delegate, to insert a QLabel displaying the QMovie inside the item (see code below).

This solution works quite nicely, and keep the display issues separated from the model. One drawback is that the display of a new frame in the label causes the entire item to be rendered again, resulting in almost continuous calls to the delegate's paint method...

To reduce the overhead inccured by these calls, I tried to minimize the work done for handling movies in the delegate by reusing the existing label if there is one. However, this results in weird behavior when resizing the windows: the animation gets shifted to the right, as if two labels were positioned side by side.

So well, here is a possible solution, feel free to comment on ways to improve it!

// Declaration

#ifndef MOVIEDELEGATE_HPP
#define MOVIEDELEGATE_HPP

#include <QtCore/QModelIndex>
#include <QtGui/QStyledItemDelegate>


class QAbstractItemView;
class QMovie;


class MovieDelegate : public QStyledItemDelegate
{
    Q_OBJECT

  public: // member functions

    MovieDelegate( QAbstractItemView & view, QObject * parent = NULL );

    void paint( QPainter * painter, 
                const QStyleOptionViewItem & option, 
                const QModelIndex & index ) const;


  private: // member functions

    QMovie * qVariantToPointerToQMovie( const QVariant & variant ) const;


  private: // member variables

    mutable QAbstractItemView & view_;
};

#endif // MOVIEDELEGATE_HPP


// Definition

#include "movieDelegate.hpp"

#include <QtCore/QVariant>
#include <QtGui/QAbstractItemView>
#include <QtGui/QLabel>
#include <QtGui/QMovie>


Q_DECLARE_METATYPE( QMovie * )


//---------------------------------------------------------
// Public member functions
//---------------------------------------------------------

MovieDelegate::MovieDelegate( QAbstractItemView & view, QObject * parent )
  : QStyledItemDelegate( parent ), view_( view )
{
}


void MovieDelegate::paint( QPainter * painter, 
                           const QStyleOptionViewItem & option, 
                           const QModelIndex & index ) const
{
    QStyledItemDelegate::paint( painter, option, index );

    const QVariant & data = index.data( Qt::DecorationRole );

    QMovie * movie = qVariantToPointerToQMovie( data );

    if ( ! movie )
    {
        view_.setIndexWidget( index, NULL );
    }
    else
    {
        QObject * indexWidget = view_.indexWidget( index );
        QLabel  * movieLabel  = qobject_cast< QLabel * >( indexWidget );

        if ( movieLabel )
        {
            // Reuse existing label

            if ( movieLabel->movie() != movie )
            {
                movieLabel->setMovie( movie );
            }
        }
        else
        {
            // Create new label;

            movieLabel = new QLabel;

            movieLabel->setMovie( movie );

            view_.setIndexWidget( index, movieLabel );
        }
    }
}


//---------------------------------------------------------
// Private member functions
//---------------------------------------------------------

QMovie * MovieDelegate::qVariantToPointerToQMovie( const QVariant & variant ) const
{
    if ( ! variant.canConvert< QMovie * >() ) return NULL;

    return variant.value< QMovie * >();
}

Qt5 Tutorial ModelView with QTableView and QItemDelegate, If the view and the controller objects are combined, the result is the model/view architecture. This still separates the way that data is stored from the way that it is� QPixmap in a QtableView cell. but I have some doubts what is the best way to do it. a very small size picture like icon in the cell and when the mouse cursor

QPixmap in a QtableView cell, I want to do it in my soft but I have some doubts what is the best way to do to its content but it looks not nice, see hereunder picture: 0_1541442936944_Picture. png. Is it a good idea to have a very small size picture like icon in the cell and photo(the itemView) disappeard as showed in the gif animation. How to Display Text on Icon Hover. I will create a list of menus so you can use a mini menu on your site if you want. The menu organized as an unordered list ul, li which is most used and best practice for navigation. It provides you an easy way to style the icons and semantically correct.

One solution is to use QMovie with GIF. I also tried using SVG (it's lightweight and offers support for transparency), but both QMovie and QImageReader don't seem to support animated SVG.

Model::Model(QObject* parent) : QFileSystemModel(parent)
{
    movie = new QMovie{ ":/resources/img/loading.gif" };
    movie->setCacheMode(QMovie::CacheAll);
    movie->start();

    connect(movie, &QMovie::frameChanged,
    [this] {
        dataChanged(index(0, 0), index(rowCount(), 0),
            QVector<int>{QFileSystemModel::FileIconRole});
    });
}

QVariant Model::data(const QModelIndex& index, int role) const
{
    case QFileSystemModel::FileIconRole:
    {
        if (index.column() == 0) {
            auto const path = QString{ index.data(QFileSystemModel::FilePathRole).toString() };

            if (path.isBeingLoaded()){
                return movie->currentImage();
            }
        }
    }
}

Model/View Tutorial, The traditional way involves widgets which include internal containers for storing data. We start with an application that uses a QTableView to show data. Writing custom delegates is the right choice if you want to show your data with a� What's the best way to embed SVGs in HTML 5? How does embedding SVGs using Img tags, Object tags, Inline SVG differs among each other in terms of browser support, alt and title attributes, browser caching, compression, interactivity, search engine indexing and workflow.

I wrote a QMovie-based solution to animate individual items in a QListView/QTableView, when they are visible (the use case was animated gifs in messages, in a chat program). The solution is similar to the QSvgRenderer solution in another answer, but it uses QMovie and it adds a "map" of currently visible indexes with a QMovie (each). See commits https://github.com/KDE/ruqola/commit/49015e2aac118fd97b7327a55c19f2e97f37b1c9 and https://github.com/KDE/ruqola/commit/2b358fb0471f795289f9dc13c256800d73accae4.

Pyqt qlistwidgetitem example, Mounds of random GUI's as you can see, icon support in PyQt is just about and I don't know how to translate it over: Is there a way to have (animated)GIF image Pyqt5 Qtablewidget Itemchanged Example PyQt v5. python,qt,pyqt,pyqt4. ctrl. QtWidgets import QListWidget, PyQt is one of the best cross-platform interface� Here are 5 unique and helpful ways to use SteelSeries OLED displays: #1: In-Game HUD. Your SteelSeries Engine features integration for a number of games including CS:GO, Dota 2, Mortal Kombat 11, Minecraft, and more. View stats at a glance such as KDA, money, health, and a ton of other options for you to customize.

Qtableview beginupdates animation movies, How to set a moving background (images) into my QWidget Qt . Filtering with What is the best way to display an animated icon in a QTableView? All Classes. Favicon Generator . The only favicon generator you need for your next project. Quickly generate your from text, image, or choose from hundreds of emojis.

Qt Programming [Archive] - Page 69, Best class for graphics-animation � Qt Eclipse plugin - linking problem of How to display in memory image in QGraphicsTextItem � Position of rows in table How to keep System tray icons � My approach to export QTableView data to a� What is the best way to show a loading spinner while the app is waiting for a response from the server? Can this be done programmatically? So that I don't have to add the load spinner in the xml f

Qt Knowledge Base, I have a QTableView showing rows of a database table. How to show icons without text in QListWidget? How to set animated icon to QPushButton in Qt5? Add visual interest to web and mobile user interfaces with our pack of 500 animated icons. Get them in multiple formats–download GIF, JSON (Lottie) and After Effects. These motion graphics are all free for a link, so go ahead and download animations to polish your checkout experience, media interactions, or social sharing.

Comments
  • I found something quite similar in QxtItemDelegate, an extension to QtItemDelegate which enable drawing progress bars (among other things). To do so, this delegate uses an approach quite similar to the one proposed in my question, but it stores views and indexes instead of painters; at each timeout of a timer, the delegate update all the views, preferably only the items that need update.
  • Note that most (all?) animated SVGs from loading.io use the <animate> tag, which seems not to be supported by QSvgRenderer, while others are (e.g. <animateColor> [deprecated in SVG], <animateTransform>). Some supported SVGs are provided by Sam Herbert: samherbert.net/svg-loaders
  • Can you provide full code, how did you write the delegate. I posted similar question for QListViewand looking for solution. stackoverflow.com/questions/31812979/…
  • @zadane The full code of the delegate is already provided in my answer. You just need to make sure your QListView uses this delegate by calling QAbstractItemView::setItemDelegate or a similar function.
  • I create same class like you did but I can't instantiate the delegate movieDelegate = new MovieDelegate( this ); gives error C:\code\svn2\Sync\mainwindow.cpp:72: error: C2664: 'MovieDelegate::MovieDelegate(QAbstractItemView &,QObject *)' : cannot convert parameter 1 from 'MainWindow *const ' to 'QAbstractItemView &' My containing view is MainWindow
  • @zadane The MovieDelegate constructor takes an additional parameter, you need to pass the view it will be assigned to (your QListView): movieDelegate = new MovieDelegate(*ui.myListView, this), or something like that..
  • thanks now compiles but It doesn't produce animation. I am setting animating gif file as the icon and just one frame shows up, no animation. new QStandardItem( QIcon( ":icons/Resources/connecting.gif"), "connecting); do I need to do anything else?