QT开发之TreeWidget、TreeView控件

本文详细介绍Qt中TreeWidget的使用方法,包括创建、显示、获取节点信息、节点操作、添加快捷菜单、自定义图标及背景颜色等。同时,提供示例代码帮助理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、TreeWidget

PS:主要是用于只有一个根节点的需求

①、显示

拖出TreeWidget控件,名称treeWidget

ui->treeWidget->setColumnCount(1); //设置列数
    ui->treeWidget->setHeaderLabel(tr("图像选择")); //设置头的标题

    QTreeWidgetItem *imageItem1 = new QTreeWidgetItem(ui->treeWidget,QStringList(QString("图像1")));
    imageItem1->setIcon(0,QIcon(":/img/1.png"));
    QTreeWidgetItem *imageItem1_1 = new QTreeWidgetItem(imageItem1,QStringList(QString("Band1"))); //子节点1
    imageItem1_1->setIcon(0,QIcon(":/img/1.png"));
    imageItem1->addChild(imageItem1_1); //添加子节点

//以此类推可以添加更多行

ui->treeWidget->expandAll(); //结点全部展开

效果:

 

②获取(单击/双击)的节点序号:

slots:
void showSelectedImage(QTreeWidgetItem*,int);//单击
void showSelectedImage2(QTreeWidgetItem*,int);//双击

//单击
connect(ui->treeWidget,SIGNAL(itemClicked(QTreeWidgetItem*,int)),this,SLOT(showSelectedImage(QTreeWidgetItem*,int)));

//双击
connect(ui->treeWidget,SIGNAL(itemActivated(QTreeWidgetItem*,int)),this,SLOT(showSelectedImage2(QTreeWidgetItem*,int)));

//单击
void QMySerialPort::showSelectedImage(QTreeWidgetItem *item, int column)//column为列号
{
    //不能判断是那个根节点,只能判断节点的序号
    QTreeWidgetItem *parent = item->parent();
    if(NULL == parent) //注意:最顶端项是没有父节点的,双击这些项时注意(陷阱)
        return;

    int number = parent->indexOfChild(item); //item在父项中的节点行号(从0开始)

    ui->pushButton->setText(QString::number(number));
}

//双击
void QMySerialPort::showSelectedImage2(QTreeWidgetItem *item, int column)//column为列号
{
    //不能判断是那个根节点,只能判断节点的序号
    QTreeWidgetItem *parent = item->parent();
    if(NULL == parent) //注意:最顶端项是没有父节点的,双击这些项时注意(陷阱)
        return;

    int number = parent->indexOfChild(item); //item在父项中的节点行号(从0开始)

    ui->pushButton->setText(QString::number(number));
}

③节点操作

.h

slots:
    void on_tv_Source_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);

public:
    QTreeWidgetItem *AddTreeRoot(QString name,QString desc);
    QTreeWidgetItem *AddTreeNode(QTreeWidgetItem *parent,QString name,QString desc);

.cpp

初始化:

ui->treeWidget->setColumnCount(1); //设置列数
    ui->treeWidget->setHeaderLabel(tr("图像选择")); //设置头的标题

    QTreeWidgetItem *imageItem1 = new QTreeWidgetItem(ui->treeWidget,QStringList(QString("图像1")));
    imageItem1->setIcon(0,QIcon(":/img/1.png"));
    QTreeWidgetItem *imageItem1_1 = new QTreeWidgetItem(imageItem1,QStringList(QString("Band1"))); //子节点1
    imageItem1_1->setIcon(0,QIcon(":/img/1.png"));
    imageItem1->addChild(imageItem1_1); //添加子节点

    ui->treeWidget->expandAll(); //结点全部展开


    connect(ui->treeWidget,SIGNAL(currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)),
            this,SLOT(on_tv_Source_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)));

    connect(ui->treeWidget,SIGNAL(itemActivated(QTreeWidgetItem*,int)),this,SLOT(showSelectedImage(QTreeWidgetItem*,int)));
    connect(ui->pushButton_2,&QPushButton::clicked,[=]()
    {
        QTreeWidgetItem * item= ui->treeWidget->currentItem();
        if(item!=Q_NULLPTR)
        {
            AddTreeNode(item,"new","new");
        }
        else
        {
            AddTreeRoot("new","new");
        }
    });
    connect(ui->pushButton_3,&QPushButton::clicked,[=]()
    {
        AddTreeRoot("new","new");
    });
    connect(ui->pushButton_4,&QPushButton::clicked,[=]()
    {
        QTreeWidgetItem * currentItem = ui->treeWidget->currentItem();

        if(currentItem==Q_NULLPTR)
        {
            return;
        }
        //如果没有父节点就直接删除
        if(currentItem->parent()==Q_NULLPTR)
        {
            delete ui->treeWidget->takeTopLevelItem(ui->treeWidget->currentIndex().row());
        }
        else
        {
            //如果有父节点就要用父节点的takeChild删除节点
            delete currentItem->parent()->takeChild(ui->treeWidget->currentIndex().row());
        }
    });
    connect(ui->pushButton_5,&QPushButton::clicked,[=]()
    {
        QTreeWidgetItem * currentItem = ui->treeWidget->currentItem();

        if(currentItem==Q_NULLPTR)
        {
            return;
        }
        for(int i=0;i<currentItem->columnCount();i++)
        {
            currentItem->setText(i,tr("Modify")+QString::number(i));
        }
    });

添加功能函数:

QTreeWidgetItem * QMySerialPort::AddTreeRoot(QString name,QString desc)
{
    QTreeWidgetItem * item=new QTreeWidgetItem(QStringList()<<name<<desc);
    ui->treeWidget->addTopLevelItem(item);
    return item;
}

QTreeWidgetItem * QMySerialPort::AddTreeNode(QTreeWidgetItem *parent,QString name,QString desc)
{
    QTreeWidgetItem * item=new QTreeWidgetItem(QStringList()<<name<<desc);
    parent->addChild(item);
    return item;
}

void QMySerialPort::on_tv_Source_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
    if(current==Q_NULLPTR)
        return;

    if(previous != Q_NULLPTR)
    {
        previous->setBackground(0,Qt::transparent);
        previous->setTextColor(0,Qt::black);
    }
    current->setTextColor(0,Qt::blue);
    current->setBackground(0,Qt::red);
}

void QMySerialPort::showSelectedImage(QTreeWidgetItem *item, int column)
{
    QTreeWidgetItem *parent = item->parent();
    if(NULL == parent) //注意:最顶端项是没有父节点的,双击这些项时注意(陷阱)
        return;

    int number = parent->indexOfChild(item); //item在父项中的节点行号(从0开始)

    ui->pushButton->setText(QString::number(number));
}

箭头所指为双击节点的序号

 

④、TreeWidget添加快捷菜单

参考:QListWidget添加快捷菜单,https://blog.youkuaiyun.com/bigtree_mfc/article/details/102607293

注意问题:

将参数const QPoint &pos换成QPoint point

customContextMenuRequested(QPoint point)

直接添加

connect(ui->treeWidget,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(on_customContextMenuRequested(QPoint)));

后续都一样

⑤、自定义展开和收缩三角形的图片

ui->treeWidget->setStyleSheet("QTreeView::branch:has-children:!has-siblings:closed,"
            "QTreeView::branch:closed:has-children:has-siblings {"
            "border-image: none;"
            "image: url(:/img/24.png);"//展开的图标
    "}"
                                  "QTreeView::branch:open:has-children:!has-siblings,"
                                 "QTreeView::branch:open:has-children:has-siblings  {"
                                          "border-image: none;"
                                          "image: url(:/img/24.png);"//收缩的图标
                                  "}");

⑥、选中背景颜色修改

connect(ui->treeWidget,&QTreeWidget::currentItemChanged,[=](QTreeWidgetItem *pItem1, QTreeWidgetItem *pItem2)
    {
        QColor m_color_cur = QColor(255,0,0);//选中的颜色修改
        pItem1->setBackgroundColor(0,m_color_cur);

        QColor m_color_pre = QColor(128,128,128);//上次选中背景色修改
        pItem2->setBackgroundColor(0,m_color_pre);
    });

⑦多选和获取状态

ui->treeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);//多选
//获取多选选中项内容
QString str;
        QList<QTreeWidgetItem*> TreeleItemList = ui->treeWidget->selectedItems();
        for(int i = 0; i < TreeleItemList.size(); i++)
        {
            str.append(TreeleItemList[i]->text(0) + ",");
        }
        str = str.left(str.size() - 1);
        qDebug() << str;

 

### Qt TableView 表头使用方法 #### 自定义水平表头 为了设置自定义的水平表头,在创建`QStandardItemModel`之后,可以利用`setHorizontalHeaderLabels()`函数指定列名。这允许开发者为每一列表明其含义。 ```cpp // 建立数据模型并设定表头名称 QStandardItemModel *model = new QStandardItemModel(4, 3); // 构造具有四行三列的数据模型实例 QStringList headers; headers << "Column1" << "Column2" << "Column3"; model->setHorizontalHeaderLabels(headers); ``` 对于更复杂的场景,比如想要显示带有图标的表头项或是其他特殊效果,则需考虑继承`QHeaderView`类来构建自己的头部视图组件[^1]。 #### 设置垂直序号表头 当涉及到给每行添加编号时,可以通过重写`paintSection()`成员函数实现这一功能。此过程涉及到了对原生绘制逻辑的部分替换: ```cpp class NumberedHeaderView : public QHeaderView { protected: void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const override { QString text = QString::number(logicalIndex + 1); painter->drawText(rect, Qt::AlignCenter, text); } }; // 使用自定义的header view替代默认版本 NumberedHeaderView* headerView = new NumberedHeaderView(Qt::Vertical, parentWidget); ui->tableView->setVerticalHeader(headerView); ``` 上述代码片段展示了如何通过派生新类的方式改变原有行为模式,从而达到预期目的——即让表格左侧显示出连续增长的自然数序列作为各行标识符[^2]。 #### 处理十六进制/二进制数值表示形式 如果希望某些特定类型的字段能够按照不同基数(如二进制或十六进制)呈现出来的话,那么应该关注于单元格编辑器(`delegate`)的设计上;不过需要注意的是,这种定制化操作主要适用于内容区域而非真正的表头部分。因此这里不再赘述具体细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值