在项目使用过程中经常出现需要选择一棵树中的某些节点,通常情况下在树节点的前面增加复选框即可;但是偶尔也有其他的设计,例如本人碰到的在树的右侧显示被选择。接下来将讲解如果在QTreeWidget的右侧显示被选择。
效果图如下:
实现方法:
1、配置树为两列
ui->treeWidget->setColumnCount(2);
ui->treeWidget->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
ui->treeWidget->header()->setSectionResizeMode(1, QHeaderView::Fixed);
ui->treeWidget->setColumnWidth(1, 14);
2、添加一颗简单的树
ui->treeWidget->header()->hide();
QStringList zhangsan;
zhangsan<<QString("张三");
QTreeWidgetItem *zhangsanroot = new QTreeWidgetItem(ui->treeWidget, zhangsan);
zhangsanroot->setData(0, Qt::UserRole, 1);//UserRole表示节点类型
zhangsanroot->setData(0, Qt::UserRole+1, 0);//UserRole+1表示节点点击状态
QStringList strLisi;
strLisi<<QString("李四");
QTreeWidgetItem *lisi = new QTreeWidgetItem(zhangsanroot, strLisi);
lisi->setData(0, Qt::UserRole, 2);
lisi->setData(0, Qt::UserRole+1, 0);
QStringList strMing;
strMing<<QString("明明");
QTreeWidgetItem *mingming = new QTreeWidgetItem(zhangsanroot, strMing);
mingming->setData(0, Qt::UserRole, 2);
mingming->setData(0, Qt::UserRole+1, 0);
3、树节点被点击的时候改变属性值
connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &TreeWidgetDialog::slotClick);
void TreeWidgetDialog::slotClick(QTreeWidgetItem *item, int column)
{
int role = item->data(0, Qt::UserRole).toInt();
if(role == 1){
//选中下面所有的
}else if(role == 2){
//选中单个
int select = item->data(0, Qt::UserRole+1).toInt();
select = !select;
item->setData(0, Qt::UserRole+1, select);
}
}
4、接下来就是重点,本人是使用代理绘制实现选择,直接上代码
下面代码是代理绘制的实现:需要重写paint和sizeHint函数;paint函数是对每个index(即每个item)的区域option.rect的适当位置进行绘制,本次就是对item的第一列左侧开始绘制一个14*14的图片,因为第一步中设置第一列为14,因此图片正好填充整列。当然有了代理绘制的实现,我们需要设置树使用下面的代理绘制:ui->treeWidget->setItemDelegate(new TreeViewDelegate);
#include <QStyledItemDelegate>
class TreeViewDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
TreeViewDelegate::TreeViewDelegate(QObject *parent = Q_NULLPTR) :
QStyledItemDelegate(parent)
{
}
void TreeViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.column() == 1){
painter->save();
QRectF iconRect = QRect(option.rect.x(),option.rect.y()+(30-14)/2, 14, 14);
QTreeWidgetItem *item = static_cast<QTreeWidgetItem*>(index.internalPointer());
int select = item->data(0, Qt::UserRole+1).toInt();
if(select){
painter->drawImage(iconRect, QImage("Y:/Documents/tcpClient1/select_c.png").scaled(14,14));
}else{
painter->drawImage(iconRect, QImage("Y:/Documents/tcpClient1/select.png").scaled(14,14));
}
painter->restore();
}
QStyledItemDelegate::paint(painter, option, index);
}
QSize TreeViewDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return QSize(250, 30);
}
};
这里我是使用代理绘制实现选中和取消选中的绘制图片不同达到选中和取消选中节点的效果。当然也可以在第1列(总共两列,第0列和第1列)放置一个按钮,可能在后面的文章中分享。