css – 为QTreeView中的不同复选框设置不同的图像

我将QTreeView子类化,我有两列有复选框.我想设置两个不同的图像:一个用于第一列,另一个用于第二列.我知道我可以在样式表中更改图像:
QTreeView::indicator:checked{
    image: url(:/checked);
}

QTreeView::indicator:unchecked{
    image: url(:/unchecked);
}

但它会更改树视图中的所有复选框.有没有办法用样式表来做,或者我需要使用委托吗?

解决方法

简短回答:样式表不能这样做(据我所知).它们在Qt中是一个非常不成熟的特性,它们似乎也没有发展.

你可以做什么:

样式表

您无法将属性分配给列或项目,也无法通过索引访问列.

但是你可以使用一些伪状态选择器,例如:first,:middle和:last:

QTreeView::indicator:first:checked{
    background: red;
}
QTreeView::indicator:middle:checked{
    background: blue;
}
QTreeView::indicator:unchecked{
    background: lightgray;
}

为简单起见,我使用颜色而不是图像.
但请注意,这些伪状态是实际当前可见的状态,因此如果允许用户对列重新排序,则列的样式可能会更改.例如,如果用户拖动其中一个:middlecolumns并将其放在最后,则该框将不再是蓝色.

decorationRole

你可以使用Qt :: decorationRole伪造它.

为此,您必须通过继承QTreeView或安装event filter来接收mousepressEvent.然后,当用户单击图标区域时,您可以更改图标(通过Qt :: decorationRole发出dataChanged()).

当然,这不适用于键盘.

自定义ItemDelegate

子类qstyledItemDelegate并覆盖paint(),就像你建议的那样.

自定义风格

如果要创建样式很重的应用程序,则可能必须迟早创建自定义样式.样式表只是不支持某些功能.

为此,子类QProxyStyle覆盖drawPrimitive并在传递qstyle :: PE_IndicatorViewItemCheck时处理绘图.您还将收到一个qstyleOptionViewItem,其中包含一些有用的属性,如checkState,features(如果有复选框,则包含qstyleOptionViewItem :: HasCheckIndicator),当然还有索引,以便您可以确定要绘制的复选框类型.

编辑:附录

使用自定义qstyledItemDelegate的示例

void MyItemDelegate::paint(QPainter * painter,const qstyleOptionViewItem & option,const QModelIndex & index) const
{
    qstyledItemDelegate::paint(painter,option,index);
    qstyleOptionViewItem opt = option;
    initStyleOption(&opt,index);

    const QWidget *widget = option.widget;
    qstyle *style = widget ? widget->style() : QApplication::style();

    QRect checkRect = style->subElementRect(qstyle::SE_ItemViewItemCheckIndicator,&opt,widget);
    drawCheckBox(painter,checkRect,opt.checkState,index);
}

void MyItemDelegate::drawCheckBox(QPainter * painter,const QRect & checkRect,Qt::CheckState checkState,const QModelIndex & index) const
{
    if (checkState == Qt::Checked)
    {
        switch (index.column())
        {
            case 0:
                painter->fillRect(checkRect,Qt::red);
                break;
            default:
                painter->fillRect(checkRect,Qt::blue);
        }
    }
    else
    {
        painter->fillRect(checkRect,Qt::lightGray);
    }
}

这个例子快速而简单.只需在qstyledItemDelegate绘制的复选框上绘制.但是需要你填满整个盒子,否则原件将是可见的.

您可以尝试使用qstyledItemDelegate绘制除复选框之外的任何内容,然后绘制复选框,但这有点难,如果您不想花太多时间在它上面会留下一些小的绘图工件.

使用自定义QProxyStyle的示例

void MyStyle::drawPrimitive(PrimitiveElement pe,const qstyleOption * opt,QPainter * p,const QWidget * w) const
{
    if (pe == qstyle::PE_IndicatorViewItemCheck)
    {
        const qstyleOptionViewItem * o = static_cast<const qstyleOptionViewItem *>(opt);
        drawCheckBox(p,opt->rect,o->checkState,o->index);
        return;
    }
    QProxyStyle::drawPrimitive(pe,opt,p,w);
}

drawCheckBox()函数与第一个示例中的相同.正如您所看到的,这种方式更简单,更清洁并且没有任何缺点.您可以全局应用样式,也可以仅应用于单个窗口小部件.

相关文章

Css3如何实现鼠标移上变长特效?(图文+视频)
css3怎么实现鼠标悬停图片时缓慢变大效果?(图文+视频)
jquery如何实现点击网页回到顶部效果?(图文+视频)
css3边框阴影效果怎么做?(图文+视频)
css怎么实现圆角边框和圆形效果?(图文+视频教程)
Css3如何实现旋转移动动画特效