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

后端 未结 5 1440
生来不讨喜
生来不讨喜 2021-02-05 19:54

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 dec

5条回答
  •  广开言路
    2021-02-05 20:28

    In my application, I have a typical spinning circle icon to indicate a waiting/processing state for some of the cells in a table. However I ended up using an approach, which is different from the one suggested in the currently accepted answer, mine is in my view simpler and somewhat more performant (UPDATE: I wrote this when a different answer was set as accepted - the one suggesting using QAbstractItemView::setIndexWidget). Using widgets seems as an overkill which will destroy the performance if there are too many of them. All the functionality in my solution is only implemented in my model layer (descendant of QAbstractItemModel) class. I do not need to make any changes in the view nor the delegate. I am however only animating one GIF and all animations are synchronized. This is the current limitation of my simple approach.

    The model class which is used to implement this behavior needs to have the following:

    • the vector of QImages - I use QImageReader, which allows me read all animation frames, I store them into a QVector

    • a QTimer ticking with the periodicity of the animated GIF - the time period is obtained using QImageReader::nextImageDelay().

    • the index (int) of the current frame (I suppose the frame is the same for all animated cells - they are synchronized; if you want unsynchronized then you can use an integer offset for each of them)

    • some knowledge of which cells should be animated and ability to translate the cell to QModelIndex (this is up to your custom code to implement this, depend on your specific needs)

    • override QAbstractItemModel::data() part of your model to respond to Qt::DecorationRole for any animated cell (QModelIndex) and return the current frame as a QImage

    • a slot which is triggered by the QTimer::timeout signal

    The key part is the slot which reacts to the timer. It must do this:

    1. Increase the current frame, e.g. m_currentFrame = (m_currentFrame + 1) % m_frameImages.size();

    2. Get the list of indices (e.g. QModelIndexList getAnimatedIndices();) of the cells which have to be animated. This code of getAnimatedIndices() is up to you to develop - use brute force querying all cells in your model or some clever optimization...

    3. emit dataChanged() signal for each animated cell, e.g. for (const QModelIndex &idx : getAnimatedIndices()) emit dataChanged(idx, idx, {Qt::DecorationRole});

    Thats all. I estimate that depending on the complexity of your functions for determining which indices are animated, the whole implementation can have something like 15 to 25 lines, without need to alter the view nor delegate, just the model.

提交回复
热议问题