【问题标题】:How do I animate the border of a list item in a QListView?如何在 QListView 中为列表项的边框设置动画?
【发布时间】:2018-05-08 19:26:36
【问题描述】:

我正在使用带有从 QStyledItemDelegate 扩展的自定义委托的 QListView。我重新实现了paint方法来自定义绘制列表中的每个项目。在paint 方法中,我在列表视图中的选定项目周围绘制了一个边框。

我希望能够在选择项目时为项目边框设置动画。例如,如果预期的项目边框是 5 像素,我希望在选择项目时让它从 0 像素到 5 像素“动画化”。

我最初的想法是连接一个计时器,使其每 50 毫秒关闭一次,并在每次计时器关闭时让委托绘制,直到绘制完整的边框宽度。但是,委托重新实现的paint方法是const,因此我无法在每次通过paint方法时保存或更新边框宽度成员变量。

最好的方法是什么?

【问题讨论】:

    标签: c++ qt qt5 qlistview qstyleditemdelegate


    【解决方案1】:

    一种可能的解决方案是创建一个角色来管理项目的边框大小,并使用QVariantAnimation 更新它:

    #include <QApplication>
    #include <QListView>
    #include <QPainter>
    #include <QStandardItemModel>
    #include <QStyledItemDelegate>
    #include <QVariantAnimation>
    
    int BorderSizeRole = Qt::UserRole+1;
    
    class AnimationDelegate: public QStyledItemDelegate{
    public:
        using QStyledItemDelegate::QStyledItemDelegate;
        void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const{
            QStyledItemDelegate::paint(painter, option, index);
    
            bool ok;
            int borderSize = index.data(BorderSizeRole).toInt(&ok);
            if(borderSize >0 && ok){
                painter->save();
                QPen pen(QBrush(Qt::red), borderSize);
                painter->setPen(pen);
                painter->drawRect(option.rect);
                painter->restore();
            }
        }
    };
    
    class CustomAnimation: public QVariantAnimation{
        QPersistentModelIndex m_index;
        QAbstractItemModel *m_model;
    public:
        CustomAnimation(QAbstractItemModel *m_model, QPersistentModelIndex index, QObject *parent=nullptr)
            : QVariantAnimation(parent),
              m_index(index),
              m_model(m_model)
        {
            setStartValue(0);
            setEndValue(5);
            setDuration(50*5);
            connect(this, &CustomAnimation::valueChanged, this, &CustomAnimation::on_valueChanged);
            // delete animation
            start(QAbstractAnimation::DeleteWhenStopped);
        }
    private:
        Q_SLOT void on_valueChanged(const QVariant & value){
            if(m_model)
                m_model->setData(m_index, value, BorderSizeRole);
            else
                stop();
        }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QListView view;
        view.setItemDelegate(new AnimationDelegate(&view));
        QStandardItemModel model;
        for(int i=0; i<10; i++){
            QStandardItem *item = new QStandardItem(QString("item %1").arg(i));
            item->setData(-1, BorderSizeRole);
            model.appendRow(item);
        }
        view.setModel(&model);
    
        QObject::connect(view.selectionModel(), &QItemSelectionModel::selectionChanged,
                         [&model](const QItemSelection &selected, const QItemSelection & deselected){
            for(const QModelIndex & index: selected.indexes()){
                new CustomAnimation(&model, QPersistentModelIndex(index));
            }
            // remove border
            for(const QModelIndex & index: deselected.indexes()){
                model.setData(index, -1, BorderSizeRole);
            }
        });
    
        view.show();    
        return a.exec();
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-11
      • 1970-01-01
      • 2011-09-23
      • 1970-01-01
      • 2017-12-05
      • 2018-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多