之前的项目中需要在QTreeWidgetItem原本图标的前面额外设置一个状态图标。
基本思路是在QStyledItemDelegate::paint()中压缩text区域,扩大icon区域,然后重新绘制图标
以下是实现方式
/*!
其他图标来自 宏 ITEMVIEW_OTHER_ICONROLE (Qt::UserRole + 11)
仅支持第二图标,如果要支持3个及以上的图标,需要改一改
第二图标默认放在原本图标前面,可以视情况调整icon_list中的图标顺序
*/
void DoubleIconDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QList<QIcon> icon_list; //图标列表,视情况调整顺序
icon_list.append(index.data(ITEMVIEW_OTHER_ICONROLE).value<QIcon>()); //第二图标
icon_list.append(index.data(Qt::DecorationRole).value<QIcon>()); //原本图标
int icon_count = icon_list.size();
int icon_size = 16; //图标尺寸,Qt默认就是这个
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
//没有图标时也占位,并设置空位宽度
opt.features |= QStyleOptionViewItem::HasDecoration;
opt.decorationSize = QSize(icon_size * icon_count, icon_size);
opt.icon = QIcon();
const QWidget *widget = option.widget;
QStyle *style = widget ? widget->style() : QApplication::style();
//调用原本的绘制方法
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
//以下开始绘制多图标
painter->save();
painter->setClipRect(opt.rect); //处理鼠标拖动压缩列宽时的遮挡效果
QRect icon_rect = style->subElementRect(QStyle::SE_ItemViewItemDecoration, &opt, widget);
int icon_margin = (icon_rect.width() - opt.decorationSize.width());
icon_rect.setLeft(icon_rect.left() + icon_margin); //恢复左侧间隔
for (int i = 0; i < icon_count; ++i)
{
const QIcon& icon = icon_list.at(i);
if (icon.isNull())
{
continue;
}
QRect temp_icon_rect = icon_rect;
temp_icon_rect.setLeft(icon_rect.left() + icon_size * i);
temp_icon_rect.setWidth(icon_size);
QIcon::Mode mode = QIcon::Normal;
if (!(opt.state & QStyle::State_Enabled))
{
mode = QIcon::Disabled;
}
else if (opt.state & QStyle::State_Selected)
{
mode = QIcon::Selected;
}
QIcon::State state = opt.state & QStyle::State_Open ? QIcon::On : QIcon::Off;
icon.paint(painter, temp_icon_rect, opt.decorationAlignment, mode, state);
}
painter->restore();
}
调用方式
QTreeWidget* tree = new QTreeWidget(this);
tree->setColumnCount(2);
tree->setItemDelegate(new DoubleIconDelegate(this));
QTreeWidgetItem* item = new QTreeWidgetItem(tree);
item->setText(0, "Test1");
item->setIcon(0, MakeIcon(Qt::red)); //常规设置图标方式
item->setData(0, ITEMVIEW_OTHER_ICONROLE, MakeIcon(Qt::black));//设置第二图标方式
item = new QTreeWidgetItem(tree);
item->setText(0, "");
item->setIcon(0, MakeIcon(Qt::cyan));
item->setData(0, ITEMVIEW_OTHER_ICONROLE, MakeIcon(Qt::green));
item = new QTreeWidgetItem(tree);
item->setText(0, "Test3");
item->setIcon(0, MakeIcon(Qt::yellow));
item->setData(0, ITEMVIEW_OTHER_ICONROLE, MakeIcon(Qt::magenta));
效果如下