【问题标题】:Set QItemDelegate on a particular QTreeWidgetItem在特定的 QTreeWidgetItem 上设置 QItemDelegate
【发布时间】:2014-12-03 14:10:50
【问题描述】:

是否可以在特定的QTreeWidgetItem 上设置QItemDelegate?我需要用特定的颜色为一些QTreeWidgetItems 着色。

我认为这是可能的,因为我们有 QAbstractItemView::setItemDelegateForRow,但我不知道怎么做。我不能使用QAbstractItemView::setItemDelegateForRow,因为我需要在QTreeWidget 内的子行上设置自定义委托。

有人知道解决办法吗?

【问题讨论】:

  • 您可以为整个小部件设置委托。然后检查委托中的项目是否适合着色
  • @Bowdzone 我可以从代表内部访问QTreeWidgetItem 吗?
  • 你还记得我上一个回答,所以你能用if(index.parent().isValid())if(index.parent().row() == 1)代替if(index.row()%2) 或者检查item的一些唯一值吗?
  • @Chernobyl 嗨,Chernobyl,是的,我记得,但我想做一个比index.row()%2 更高级的检查,我会检查树小部件项是否具有某个属性集,例如(考虑到我有一个自定义的QTreeWidgetItem 实现了其他成员函数)。
  • @JacobKrieg 是的,你可以。我不记得我是怎么做到的,因为我现在无法访问我的那个项目。如果我记得我会在 1-2 小时内发布一个示例

标签: qt qtreewidget qtreewidgetitem qitemdelegate


【解决方案1】:

您不能在委托中直接使用QTreeWidgetItem(可能您可以在委托中存储这些项目的列表,但我认为它效率不高),因为委托与QModelIndex 和不同角色内的数据一起使用。您可以将数据设置为Qt::UserRole+1 并在委托中访问它。例如:

QTreeWidgetItem *cities = new QTreeWidgetItem(ui->treeWidget);
//...
cities->setData(0,Qt::UserRole+1,"chosen one");

QTreeWidgetItem *osloItem = new QTreeWidgetItem(cities);
//...

QTreeWidgetItem *berlinItem = new QTreeWidgetItem(cities);
//...
berlinItem->setData(0,Qt::UserRole+1,"chosen one");

内部委托(仅举例):

    void ItemDelegatePaint::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QString txt = index.model()->data( index, Qt::DisplayRole ).toString();

    if( option.state & QStyle::State_Selected )
    {
        if(index.data(Qt::UserRole+1).toString() == "chosen one")
            painter->fillRect( option.rect,Qt::green );
        else
            painter->fillRect( option.rect, option.palette.highlight() );
    }else
    if(option.state & QStyle::State_MouseOver)
    {
        if(index.data(Qt::UserRole+1).toString() == "chosen one")
            painter->fillRect( option.rect,Qt::yellow );
        else
            painter->fillRect( option.rect, Qt::transparent );
    }
    else
    {
        QStyledItemDelegate::paint(painter,option,index);
    }
}

【讨论】:

  • 你说的很有趣,我认为它会起作用。但是Qt::UserRole + 1 不是一个小黑客吗? :-)
  • @JacobKrieg 显示角色用于显示,editrole 用于编辑,decorationrole 用于图像等,现在您需要其他信息,并且使用Qt::UserRole + 1。当然使用 1 或 0 而不是选择一个更好。这不是什么坏事,无论如何 QTreeWidget + QTreeWidgetItem 比自定义 QAbstractItemModel 消耗更多的空间(Summerfield 在书中证明了这一点)所以我认为这几个 KB 或 MB 不会破坏你的项目。
  • 谢谢!让我们等待@Bowdzone 发布他的解决方案,我也很好奇他的想法。
  • @JacobKrieg 有人可能认为我错了,我想澄清一下。使用 QAbstractItemModel + QTreeView 我们可以比使用 QTreeWidget + QTreeWidgetItem 实现更多,如果我们做得很好并且任务不会很困难,我们可以说 QAbstractItemModel + QTreeView 更有效。但是自定义 QAbstractItemModel 需要大量的工作,非常大的工作,所以正如 Summerfield 所写: ...使用 QStandardItemModel(或 QTreeWidget 在你的情况下)可以为我们节省很多工作
  • 你是对的!然而,在这种情况下,我不得不像这样工作,因为我正在处理的代码是遗留的并且“由不了解 qt 的人编写”代码。这很痛苦,但在重构的时间到来之前,我想我得自己动手了。
【解决方案2】:

您可以从您委托的绘制例程中访问QTreeWidget,以检查是否满足绘制背景的条件

void custom_delegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    const QTreeWidget* tree_widget = qobject_cast<const QTreeWidget*>(qstyleoption_cast<const QStyleOptionViewItemV3*>(&option)->widget);
    ....
}

或者您按照切尔诺贝利的建议将某些内容存储在 QModelIndex UserData 中。在这种情况下,我会为标志创建一个enum(如果这适用于您的情况):

enum custom_painter_flags{
    paint_default = 0,
    paint_background = 1
};

void somewhere_creating_the_items()
{
    QTreeWidgetItem* newitem = new QTreeWidgetItem(...);
    newitem->setData(0, Qt::UserRole, QVariant::fromValue<int>(custom_painter_flags::paint_background));
}

void custom_delegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    custom_painter_flags painter_flags = static_cast<painter>(index.data(Qt::UserRole).value<int>());

    if(painter_flags & paint_background){
        ....
    }
}

不幸的是,我现在没有太多时间,所以很快就整理好了。如果您发现任何错误,请随时编辑。

【讨论】:

  • 我考虑过铸造小部件,但它打破了我的所有观点。例如:const QTreeWidget* tree_widget =... 工作正常,但之后qDebug() &lt;&lt; tree_widget-&gt;currentItem()-&gt;text(0); 例如中断所有视图。和QPaintDevice: Cannot destroy paint device that is being painted打断了可能是我误解了如何使用它?
  • 对不起,我没有办法解决这个问题
  • 像魅力一样工作。我结合了你的答案和@Chernobyl 的答案。不幸的是,我不能同时接受这两个答案,所以我会支持他的并接受你的。我希望没有人会太沮丧:-s 节日快乐!
【解决方案3】:

您可以在 QTreeWidgetItem 上使用 qss 来更改颜色或背景颜色。

【讨论】:

  • 确实,你是对的,但你不能为某些QTreeWidgetItems 更改颜色,也不能只使用QSS 为其他人更改颜色。这就是我创建自定义委托的原因。但我不知道如何在QTreeWidget 中的某些QTreeWidgetItems 或QModelIndexes 上设置它。
【解决方案4】:

我已经为 QTableWidget 做了,您必须检查所有 QTreeWidgetItem 的值并设置背景颜色/颜色。

例如,对于我的 QTableWidget,我在一个循环中做了这样的事情:

如果(好项目): MyQTableItem.setBackground(QtGui.QColor(255,255,255))

【讨论】:

  • 是的,你是对的,但你不能为项目的悬停或选定状态自定义文本颜色。这就是为什么我为此选择了一个自定义委托。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-14
  • 2020-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
相关资源
最近更新 更多