мне нужно сделать что-нибудь еще?

олся с этим уже несколько раз, и я не могу найти правильный способ сделать это.

Что я хотел бы, так это возможность использовать анимированный значок в качестве украшения для некоторых из моих предметов (как правило, чтобы показать, что для этого конкретного предмета происходит некоторая обработка). У меня есть пользовательская модель таблицы, которую я отображаю вQTableView.

Моей первой идеей было создать пользовательский делегат, который позаботится об отображении анимации. Когда прошлоQMovie на роль декорации делегат должен подключиться кQMovie для обновления дисплея каждый раз, когда доступен новый кадр (см. код ниже). Тем не менее, художник, кажется, не остается в силе после вызова делегатаpaint метод (я получаю ошибку при вызове художникаsave метод, вероятно, потому что указатель больше не указывает на правильную память).

Другим решением будет испусканиеdataChanged сигнал об элементе каждый раз, когда доступен новый кадр, но 1) который вызовет много ненужных служебных данных, поскольку данные на самом деле не изменяются; 2) управление фильмом на уровне модели кажется не совсем чистым: ответственность должна лежать на уровне дисплея (QTableView или делегат) для обработки отображения новых кадров.

Кто-нибудь знает чистый (и желательно эффективный) способ отображения анимации в представлениях Qt?

Для тех, кто заинтересован, вот код делегата, которого я разработал (который не работает в данный момент).

// 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 * >();
}

Ответы на вопрос(1)

Ваш ответ на вопрос