在QTreeView中覆盖QStyledItemDelegate中的文本

7

我在使用QStyledItemDelegate覆盖QTreeView中显示的文本时遇到了问题。 当满足某些条件时,将执行以下代码:

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
  .
  .

        QStyleOptionViewItemV4 opt = option;
        initStyleOption(&opt, index);
        QString text = opt.text;
        text = text + QString("TEST");
        opt.text = text;

        QStyledItemDelegate::paint(painter, opt, index);
}

在调试器中我确认TEST被添加到opt.text中。
然而,当我运行程序并查看TreeVuew时,它仍然显示原始文本,没有追加TESTstring

看起来当我调用QStyledItemDelegate::paint(painter, opt, index)时,它忽略了我对opt参数所做的更改。

4个回答

4

QStyledItemDelegate::paint() 方法的默认实现使用自己的 QStyleOptionViewItem 实例,该实例使用来自模型的数据进行初始化。

来自 Qt 5.4.0 源代码:

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

    QStyleOptionViewItem opt = option;
    initStyleOption(&opt, index);

    const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
    QStyle *style = widget ? widget->style() : QApplication::style();
    style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
}

解决方案:

不要调用默认实现,而是像这样实现您的委托的 paint() 方法:

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

    initStyleOption(&itemOption, index);
    itemOption.text = "Test Text";  // override text

    QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &itemOption, painter, nullptr);
}

3

如果你想要改变视图中显示的文本,另一种解决方案是覆盖displayText()方法。

Qt5的示例:

mydelegate.h

virtual QString displayText(const QVariant &value,
                            const QLocale &locale) const override;

mydelegate.cpp

QString MyDelegate::displayText(const QVariant &value,
                                          const QLocale &locale) const
{
    Q_UNUSED(locale)
    QString result = value.toString() + "TEST";
    return result;
}

文档链接: https://doc.qt.io/qt-5/qstyleditemdelegate.html#displayText


0

可能 QStyledItemDelegate::paint 直接从 index.data(Qt::DisplayRole).toString() 中获取文本。这就是为什么文本没有改变的原因。您可以通过 Qt 源代码进行调试以确保。

我建议您使用 QIdentityProxyModel 来完成此类操作。委托不是为这样的解决方案而设计的。您只需要重写一个方法即可。所以您的代码应该像这样:

class MyProxyModel : public QIdentityProxyModel
{
  // ...
};

QVariant MyProxyModel::data(const QModelIndex &index, int role) const override
{
  if (  /*Conditions when you don't want to change source text*/ )
    return QIdentityProxyModel::data( index, role );

  // Extra check for editors or other roles to return original data
  if ( role == Qt::EditRole || role != Qt::DisplayRole )
    return QIdentityProxyModel::data( index, role );

  const auto sourceIndex = mapToSource( index );
  const auto originalText = sourceModel()->data( sourceIndex, Qt::DisplayRole ).toString();
  const auto newText = QString( "%1 [TEST]" ).arg( originalText );

  return newText;
}

// Usage
auto yourModel = YourOriginalModel( this );
auto proxy = MyProxyModel( this );
proxy->setSourceModel( yourModel );
view->setModel( proxy );

0

根据委托类型的不同,我还会尝试重写setEditorData()方法甚至是createEditor()方法(在这里您可以添加与模型不同的值)。这比在绘制中执行此类操作要少耗费时间。

否则,您可以使用类似以下代码来在所需位置绘制文本:

painter->drawText(option.rect, Qt::AlignJustify, text + "_test");

你可能有自己的原因,但是如果你想要动态添加额外的文本,那么你的设计似乎存在问题。


1
编辑器不会影响显示,对吧?我认为只有在您实际尝试更改项目时才会发挥作用。 - JonF

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接