【问题标题】:How to change icon using delegate in Qt如何在 Qt 中使用委托更改图标
【发布时间】:2014-08-22 10:13:20
【问题描述】:

我在 Qtreeview 中使用了一个委托,它只在文本旁边显示一个图标。

我希望能够做的是单击列表中的一项并仅更改该一项的图标。我一直在查看一些示例,但它们都使用了我不想使用的编辑器。我希望更改在项目的点击操作上自动发生。

我猜我将不得不使用我单击的项目的索引向我的委托类添加一个新函数,这很好,但是如何更改图标?我是否必须用新图标调用绘画功能才能绘画?

这是我正在使用的委托:

void SeqNavDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
       const QModelIndex &index) const
{
    QStyledItemDelegate::paint(painter, option, index);

    if (index.column() == 0 && option.state & QStyle::State_Enabled)//State_MouseOver)
    {
        const QIcon icon(QLatin1String(":/SeqNavMenu/images/grey.png"));

        QRect iconRect(option.rect.right() - option.rect.height(),
                       option.rect.top(),
                       option.rect.height(),
                       option.rect.height());

        icon.paint(painter, iconRect, Qt::AlignRight);
    }
}

我只是用不同的图标路径重新实现这个功能吗?

感谢您的帮助。

【问题讨论】:

    标签: c++ qt delegates


    【解决方案1】:

    处理一次点击

    让我们从用户点击一行开始。订阅QAbstractItemView 的信号clicked (const QModelIndex&)

    根据Model/View 的概念,视图显示模型提供的数据。要显示文本,您已经在模型中重新实现了方法data,并且模型开始提供文本。现在您要显示图标。在只需要显示一个图标之前,您可以通过委托来完成。现在您需要让您的模型提供所需的图标或可以选择图标的状态。
    为了提供一个图标,模型应该知道应该为每一行显示哪个图标。创建一个变量以保持每行的单击状态。

    在连接到clicked的槽中,信号通知模型一行的点击状态发生了变化:

     {
       bool oldState = m_model->data(index, Qt::UserRole).toBool();
       m_model->setData(index, !oldState, Qt::UserRole);
     }
    

    Qt:UserRole的处理添加到setData

    {
      if (role == Qt:UserRole)
        setClickedState(index, value.toBool());
    }
    

    不要忘记通知视图您在此行中的数据已更改。在setData 结束时调用emit dataChanged(index, index)。这就是您的问题的答案,如何使视图重新绘制。它会在收到您的信号后立即重新绘制。

    Qt:UserRole的处理添加到data

    if (role == Qt::UserRole)
       return clickedState(index);
    

    向代理询问点击状态并绘制所需图标

    const QAbstractItemModel* model = index.model();
    const bool state = model->data(index, Qt::UserRole).toBool();
    const QIcon& iconToBeDrawn = state ? checkedIcon : icon;
    

    附言 您出于错误的目的使用自定义委托。当您需要绘制无法使用标准 QStyledItemDelegate 绘制的东西时,需要自定义委托。但它可以绘制图标。
    要绘制图标,您需要在模型中处理 Qt::DecorationRole,如下所示:

    virtual QVariant data (const QModelIndex& index, int role) const
    {
      ...
      if (role == Qt::DecorationRole)
            return someIcon;
      ...
    }
    

    QStyledItemDelegate默认在左侧绘制一个图标。在我的评论中,我向您建议如何将其绘制在一行的右侧: Delegate erasing text in QTreeView using QStandardItemModel

    与为每一行提供文本的方式相同,您可以提供一个图标:

    if (role == Qt::DecorationRole)
       return ifClicked(index) ? someIcon : otherIcon;
    

    【讨论】:

      【解决方案2】:

      实际上,通过在 QStyledItemDelegate 的派生中重新实现 initStyleOption() 非常简单。我需要代表文件夹的项目将图标从关闭更改为打开以响应用户操作:

      class MyDelegate : public QStyledItemDelegate
      {
      public:
          MyDelegate(QObject *parent = 0)
              : QStyledItemDelegate(parent)
          {
          }
      protected:
          virtual void initStyleOption(QStyleOptionViewItem * option, const QModelIndex & index) const
          {
              QStyledItemDelegate::initStyleOption(option, index);
              if (QStyleOptionViewItemV4 *v4 = qstyleoption_cast<QStyleOptionViewItemV4 *>(option))
              {
                  const MyModel *model(static_cast<const MyModel *>(index.model()));
                  if ((option->state & QStyle::State_Open) && model->isFolderItem(index))
                      v4->icon = QIcon(toFolderIconStr(true));
              }
          }
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-06-10
        • 1970-01-01
        • 2019-11-18
        • 1970-01-01
        • 1970-01-01
        • 2019-03-26
        • 2012-11-28
        相关资源
        最近更新 更多