gpt4 book ai didi

c++ - 是否可以在 QStyledItemDelegate 中为 QIcon 的不透明度设置动画?

转载 作者:行者123 更新时间:2023-11-28 07:08:54 26 4
gpt4 key购买 nike

上下文

我有一个 QTreeViewQStandardItemModel .我的模型可以更改为以 4 种不同的模式显示它的项目:

  1. 0 级:艺术家 1 级:专辑 2 级:轨道
  2. 0 级:艺术家 - 专辑 1 级:轨道
  3. 0 级:专辑 1 级:轨道
  4. 0 级:年份 1 级:艺术家 - 专辑 2 级:轨道

我创建了 QStyledItemDelegate 的子类以显示星星(如 Star Delegate Example )

在模式 2 或 3 中,可以在选项中启用封面相册(并设置大小,如 64 x 64 像素)。

为了减少内存占用,当项目显示在屏幕上时,封面会延迟加载。每次启动音频播放器时,没有后台进程扫描硬盘。

它运行良好,但用户体验有待改进。事实上,通过使用滚轮鼠标,可以毫无问题地加载封面。当使用垂直滚动条时,在 500 个相册库中向下移动它,加载 *.jpeg 或 *.png 时您可以听到硬盘驱动器的抓取声。加载所有封面后,滚动非常流畅(我需要稍后处理它们)。

这是我到目前为止所做的:

我已将 QScrollBar 子类化并检测到 MousePressEventMouseReleaseEvent暂时禁用加载。

我在单击滚动条时创建了一个信号,并将其连接到我的 QStyledItemDelegate。但是,封面在屏幕上“弹出”。

我在找什么:

我想顺利显示,用QPropertyAnimation类(和 Animation Framework )。遗憾的是,QStyledItemDelegate、QIcon、QStandardItem 不是 QObject 也不是 QWidget,所以我不能使用 2 或 3 行代码来创建这种动画。

是否有解决方法或某种(不是那么丑陋的)黑客攻击?

我宁愿不覆盖 paintEvent 以在我的 QTreeView 中从头开始重新创建所有内容,因为这似乎很难做到,但也许我错了。

最佳答案

好吧,我没有找到使用 QPropertyAnimation 的正确方法,所以这里有一个更复杂的解决方案。

类库滚动条

void LibraryScrollBar::mouseMoveEvent(QMouseEvent *e)
{
if (_hasNotEmittedYet) {
qDebug() << "hide covers when moving";
emit displayItemDelegate(false);
_hasNotEmittedYet = false;
}
QScrollBar::mouseMoveEvent(e);
}

void LibraryScrollBar::mouseReleaseEvent(QMouseEvent *e)
{
if (!_hasNotEmittedYet) {
qDebug() << "show covers when stopped moving";
emit displayItemDelegate(true);
_hasNotEmittedYet = true;
}
QScrollBar::mouseReleaseEvent(e);
}

在类 LibraryTreeView 中

void LibraryTreeView::init(LibrarySqlModel *sql)
{
/// some code before
LibraryScrollBar *vScrollBar = new LibraryScrollBar(this);
this->setVerticalScrollBar(vScrollBar);
connect(vScrollBar, &LibraryScrollBar::displayItemDelegate, [=](bool b) {
_itemDelegate->displayIcon(b);
b ? _timer->start() : _timer->stop();
});
connect(_timer, &QTimer::timeout, this, &LibraryTreeView::repaintIcons);
}

void LibraryTreeView::repaintIcons()
{
static qreal r = 0;
if (_timer->isActive()) {
r += 0.01;
_itemDelegate->setIconOpacity(r);
if (r >= 1) {
_timer->stop();
r = 0;
}
this->viewport()->repaint();
}
}

在类 LibraryItemDelegate 中

void LibraryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
painter->save();
painter->setFont(Settings::getInstance()->font(Settings::LIBRARY));
QStandardItem *item = _libraryModel.data()->itemFromIndex(_proxy.data()->mapToSource(index));
QStyleOptionViewItem o = option;
initStyleOption(&o, index);

// Removes the dotted rectangle to the focused item
o.state &= ~QStyle::State_HasFocus;
int type = item->data(LibraryTreeView::Type).toInt();
switch (type) {
case LibraryTreeView::Album:
this->drawAlbum(painter, o, item);
break;
/// etc
}
painter->restore();
}

/** Albums have covers usually. */
void LibraryItemDelegate::drawAlbum(QPainter *painter, QStyleOptionViewItem &option, QStandardItem *item) const
{
static QImageReader imageReader;
static int coverSize = Settings::getInstance()->coverSize();
QString file = item->data(LibraryTreeView::DataCoverPath).toString();
// Display a light selection rectangle when one is moving the cursor
if (option.state & QStyle::State_MouseOver && ~option.state & QStyle::State_Selected) {
painter->save();
painter->setPen(option.palette.highlight().color());
painter->setBrush(option.palette.highlight().color().lighter(175));
painter->drawRect(option.rect.adjusted(0, 0, -1, -1));
painter->restore();
} else if (option.state & QStyle::State_Selected) {
// Display a not so light rectangle when one has chosen an item. It's darker than the mouse over
painter->save();
painter->setPen(option.palette.highlight().color());
painter->setBrush(option.palette.highlight().color().lighter(160));
painter->drawRect(option.rect.adjusted(0, 0, -1, -1));
painter->restore();
}
if (_showCovers) {
/// XXX: extract this elsewhere
// Qt::UserRole + 20 == false => pixmap not loaded ; == true => pixmap loaded
if (item->data(Qt::UserRole + 20).toBool() == false && !file.isEmpty()) {
FileHelper fh(file);
QFileInfo f(file);
qDebug() << "loading cover from harddrive";
// If it's an inner cover, load it
if (FileHelper::suffixes().contains(f.suffix())) {
std::unique_ptr<Cover> cover(fh.extractCover());
if (cover) {
QPixmap p;
p.loadFromData(cover->byteArray(), cover->format());
p = p.scaled(coverSize, coverSize);
item->setIcon(p);
item->setData(true, Qt::UserRole + 20);
}
} else {
imageReader.setFileName(QDir::fromNativeSeparators(file));
imageReader.setScaledSize(QSize(coverSize, coverSize));
item->setIcon(QPixmap::fromImage(imageReader.read()));
item->setData(true, Qt::UserRole + 20);
}
}
}
bool b = item->data(Qt::UserRole + 20).toBool();
if (_showCovers && b) {
QPixmap p = option.icon.pixmap(QSize(coverSize, coverSize));
QRect cover(option.rect.x() + 1, option.rect.y() + 1, coverSize, coverSize);
if (_animateIcons) {
painter->save();
painter->setOpacity(_iconOpacity);
painter->drawPixmap(cover, p);
painter->restore();
} else {
painter->drawPixmap(cover, p);
}
}
// It's possible to have missing covers in your library, so we need to keep alignment.
QPoint topLeft(option.rect.x() + coverSize + 5, option.rect.y());
QFontMetrics fmf(Settings::getInstance()->font(Settings::LIBRARY));
QRect rectText(topLeft, option.rect.bottomRight());
option.textElideMode = Qt::ElideRight;
QString s = fmf.elidedText(option.text, Qt::ElideRight, rectText.width());
painter->drawText(rectText, Qt::AlignVCenter, s);
}

关于c++ - 是否可以在 QStyledItemDelegate 中为 QIcon 的不透明度设置动画?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21331595/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com