我一直在爲此奮鬥一段時間,我似乎無法找到正確的方式來做到這一點。什麼是在QTableView中顯示動畫圖標的最佳方式?
我想是使用動畫圖標爲我的一些物品裝飾(通常表明一些處理正在發生的這個特殊項目)的能力。我有一個自定義表模型,我在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 * >();
}
我發現非常類似的東西[`QxtItemDelegate`(http://www.koders.com/cpp/fid5911A4434425C7038B6C507A5BF978C82A6294FD.aspx),擴展到`QtItemDelegate`這使繪製進度條(除其他事項外)。爲此,該代表使用與我的問題中提出的方法非常相似的方法,但它存儲視圖和索引而不是畫家;在計時器的每次超時時,委託人都會更新所有視圖,最好只是需要更新的項目。 – 2010-12-09 09:29:10