C++ Qt開發:TreeWidget 樹形選擇組件

来源:https://www.cnblogs.com/LyShark/archive/2023/12/18/17908946.html
-Advertisement-
Play Games

Qt 是一個跨平臺C++圖形界面開發庫,利用Qt可以快速開發跨平臺窗體應用程式,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現圖形化開發極大的方便了開發效率,本章將重點介紹`TreeWidget`樹形選擇組件的常用方法及靈活運用。`QTreeWidget` 是 Qt 中的樹形控制項組件,... ...


Qt 是一個跨平臺C++圖形界面開發庫,利用Qt可以快速開發跨平臺窗體應用程式,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現圖形化開發極大的方便了開發效率,本章將重點介紹TreeWidget樹形選擇組件的常用方法及靈活運用。

QTreeWidget 是 Qt 中的樹形控制項組件,用於顯示樹形結構的數據。它繼承自 QTreeViewQTreeWidget,提供了一個方便的方式來展示和編輯包含層次結構數據的項目。

以下是 QTreeWidget 類的一些常用方法,說明和概述:

方法 描述
addTopLevelItem(QTreeWidgetItem *item) 向樹中添加一個頂級項目。
addTopLevelItems(const QList<QTreeWidgetItem *> &items) 向樹中添加多個頂級項目。
clear() 清除樹中的所有項目。
currentItem() 返回當前選擇的項目。
currentIndex() 返回當前選擇的項目的模型索引。
editItem(QTreeWidgetItem *item, int column) 進入編輯模式以編輯給定項目的指定列。
headerItem() 返回樹的標題項目,該項目可用於設置標題標簽。
invisibleRootItem() 返回樹的不可見根項目。
itemAbove(QTreeWidgetItem *item) 返回給定項目的上面一個項目。
itemBelow(QTreeWidgetItem *item) 返回給定項目的下麵一個項目。
setCurrentItem(QTreeWidgetItem *item) 設置當前選擇的項目。
topLevelItem(int index) 返回樹中給定索引的頂級項目。
topLevelItemCount() 返回樹的頂級項目的數量。
insertTopLevelItem(int index, QTreeWidgetItem *item) 在給定索引處插入一個頂級項目。
insertTopLevelItems(int index, const QList<QTreeWidgetItem *> &items) 在給定索引處插入多個頂級項目。
takeTopLevelItem(int index) 從樹中移除給定索引處的頂級項目,並返回該項目的指針。
scrollToItem(QTreeWidgetItem *item, QAbstractItemView::ScrollHint hint = EnsureVisible) 滾動樹以確保給定項目可見。
sortItems(int column, Qt::SortOrder order = Qt::AscendingOrder) 對樹中的項目進行排序。
findItems(const QString &text, Qt::MatchFlags flags, int column = 0) 查找樹中包含指定文本的項目。

這隻是 QTreeWidget 類的一小部分方法。你可以查閱官方文檔以獲取完整的方法列表,以及這些方法的詳細說明。

首先我們來繪製一下UI界面,由於該節點同時具備編輯功能所以實現起來要稍微複雜一些,我們分別在最左側放置一個TreeWidget組件,在中間放置不同的PushButton組件,最後是一個plainTextEdit組件用來接收反饋,如下圖所示;

1.1 初始化組件

如下代碼是在 Qt 中使用 QTreeWidget 初始化一個樹形結構,其中包含了朋友、同學和陌生人等不同分類的節點。

以下是概述:

  1. 初始化 QTreeWidget 設置 QTreeWidget 的一些基本屬性,包括列數、標題的隱藏等。
  2. 創建父節點 "朋友": 使用 QTreeWidgetItem 創建一個朋友節點,並設置圖標、選擇狀態等屬性。然後添加兩個子節點 "老張" 和 "老王",分別設置圖標和選擇狀態。
  3. 創建父節點 "同學": 類似地,創建一個同學節點,並添加兩個子節點 "張三" 和 "李四",設置相應的圖標和選擇狀態。
  4. 創建 "陌生人" 節點: 使用 QTreeWidgetItem 直接創建一個陌生人節點,並設置文本和圖標。
  5. 將節點添加到 QTreeWidget 中: 使用 addTopLevelItem 將 "同學" 和 "陌生人" 節點添加到 QTreeWidget 的頂級。
  6. 展開所有節點: 使用 expandAll 展開所有節點,使其在初始化時可見。
  7. 設置 QTreeWidget 的大小: 使用 resize 設置 QTreeWidget 的大小。

這段代碼的主要功能是創建一個包含不同分類和子節點的樹形結構,每個節點可以有不同的圖標、文本和選擇狀態。在展示的樹形結構中,朋友和同學節點有子節點,而陌生人節點沒有子節點。這個示例展示了 QTreeWidget 用於創建層次結構的基本用法。

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->treeWidget->clear();

    // ----------------------------------------------
    // 初始化TreeWidget組件
    // ----------------------------------------------

    // 設置QTreeWidget的列數
    ui->treeWidget->setColumnCount(1);

    // 設置QTreeWidget標題隱藏
    ui->treeWidget->setHeaderHidden(true);

    // ----------------------------------------------
    // 創建QTreeWidget的朋友節點 此時的父節點是TreeWidget
    // ----------------------------------------------

    QTreeWidgetItem *Friend = new QTreeWidgetItem(ui->treeWidget,QStringList(QString("朋友")));
    Friend->setIcon(0,QIcon(":/image/4.ico"));
    Friend->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable
                     | Qt::ItemIsEnabled | Qt::ItemIsAutoTristate);
    Friend->setCheckState(0,Qt::Checked);

    // 給Friend添加一個子節點frd
    QTreeWidgetItem *frd = new QTreeWidgetItem(Friend);
    frd->setText(0,"老張");
    frd->setIcon(0,QIcon(tr(":/image/1.ico")));
    frd->setCheckState(0,Qt::Checked);

    // 繼續給Friend添加一個子節點frs
    QTreeWidgetItem *frs = new QTreeWidgetItem(Friend);
    frs->setText(0,"老王");
    frs->setIcon(0,QIcon(tr(":/image/1.ico")));
    frs->setCheckState(0,Qt::Unchecked);

    // ----------------------------------------------
    // 繼續創建名叫同學節點 父節點同樣是TreeWidget
    // ----------------------------------------------
    QTreeWidgetItem * ClassMate = new QTreeWidgetItem(ui->treeWidget,QStringList(QString("同學")));
    ClassMate->setIcon(0,QIcon(":/image/5.ico"));
    ClassMate->setCheckState(0,Qt::Checked);

    // Fly是ClassMate的子節點
    QTreeWidgetItem *Fly = new QTreeWidgetItem(QStringList(QString("張三")));
    Fly->setIcon(0,QIcon(tr(":/image/2.ico")));

    // 創建子節點的另一種方法
    ClassMate->addChild(Fly);
    Fly->setCheckState(0,Qt::Checked);

    // 繼續創建子節點Fls
    QTreeWidgetItem *Fls = new QTreeWidgetItem(QStringList(QString("李四")));
    Fls->setIcon(0,QIcon(tr(":/image/2.ico")));
    ClassMate->addChild(Fls);
    Fls->setCheckState(0,Qt::Checked);       // 設置為選中

    // ----------------------------------------------
    // 創建陌生人節點
    // ----------------------------------------------
    QTreeWidgetItem  *Strange = new QTreeWidgetItem(true);
    Strange->setText(0,"陌生人");
    Strange->setIcon(0,QIcon(":/image/6.ico"));

    ui->treeWidget->addTopLevelItem(ClassMate);
    ui->treeWidget->addTopLevelItem(Strange);

    // 展開QTreeWidget的所有節點
    ui->treeWidget->expandAll();
    ui->treeWidget->resize(271,401);
}

代碼運行後可動態對左側組件進行初始化,並增加應有的父節點與子節點,如下圖;

1.2 添加根節點

如下槽函數,其核心功能是在 QTreeWidget 中添加一個新的頂級父節點,併在 QPlainTextEdit 中添加一行文本記錄。

以下是概述:

  1. 獲取節點文本: 使用 QString NodeText = "新的父節點"; 設置新父節點的文本。
  2. 創建新的 QTreeWidgetItem 使用 QTreeWidgetItem 的構造函數創建一個新的頂級父節點,並設置其文本和圖標。
  3. 添加節點到 QTreeWidget 中: 使用 ui->treeWidget->addTopLevelItem(item); 將新的頂級父節點添加到 QTreeWidget 中。
  4. 記錄操作到 QPlainTextEdit 中: 使用 ui->plainTextEdit->appendPlainText("添加新的父節點"); 將一行文本記錄添加到 QPlainTextEdit 中,用於記錄操作。

這段代碼的作用是在點擊按鈕時,在 QTreeWidget 中添加一個新的頂級父節點,併在 QPlainTextEdit 中記錄這一操作。這樣可以用於在界面上動態添加樹節點,並記錄相關的操作信息。

void MainWindow::on_pushButton_add_clicked()
{
    QString NodeText = "新的父節點";
    QTreeWidgetItem  *item = new QTreeWidgetItem(true);
    item->setText(0,NodeText);
    item->setIcon(0,QIcon(":/image/7.ico"));
    ui->treeWidget->addTopLevelItem(item);
    ui->plainTextEdit->appendPlainText("添加新的父節點");
}

運行後通過點擊添加根節點按鈕,每次則可以生成一個根,如下圖;

1.3 添加子節點

如下槽函數,其核心功能是在 QTreeWidget 中添加新的子節點,併在 QPlainTextEdit 中添加一行文本記錄。

以下是概述:

  1. 獲取當前選擇的節點: 使用 QTreeWidgetItem * item= ui->treeWidget->currentItem(); 獲取當前在 QTreeWidget 中選擇的節點。
  2. 判斷是否有選擇的節點: 使用 if(item!=NULL) 條件判斷,如果存在選擇的節點,則調用 AddTreeNode 函數添加子節點;否則,調用 AddTreeRoot 函數添加新的根節點。
  3. 添加子節點或新的根節點:
    • 如果存在選擇的節點,調用 AddTreeNode(item,"新子節點","新子節點"); 添加一個新的子節點,其文本和圖標分別為 "新子節點"。
    • 如果沒有選擇的節點,調用 AddTreeRoot("新子節點","新子節點"); 添加一個新的根節點,其文本和圖標同樣為 "新子節點"。
  4. 記錄操作到 QPlainTextEdit 中: 使用 ui->plainTextEdit->appendPlainText("添加新的子節點"); 將一行文本記錄添加到 QPlainTextEdit 中,用於記錄操作。

這段代碼的作用是在點擊按鈕時,根據用戶當前選擇的節點狀態,在 QTreeWidget 中添加新的子節點或新的根節點,並記錄這一操作到 QPlainTextEdit 中。

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

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

void MainWindow::on_pushButton_addsubnode_clicked()
{
    QTreeWidgetItem * item= ui->treeWidget->currentItem();
        if(item!=NULL)
            AddTreeNode(item,"新子節點","新子節點");
        else
            AddTreeRoot("新子節點","新子節點");

        ui->plainTextEdit->appendPlainText("添加新的子節點");
}

子節點的添加依賴於封裝好的兩個AddTreeNode函數,通過調用後則可以在父節點上添加子節點,如下圖;

1.4 修改選中節點

如下槽函數,其核心功能是修改 QTreeWidget 中當前選中節點的文本和圖標,併在 QPlainTextEdit 中添加一行文本記錄。

以下是概述:

  1. 獲取當前選中的節點: 使用 QTreeWidgetItem *currentItem = ui->treeWidget->currentItem(); 獲取當前在 QTreeWidget 中選擇的節點。
  2. 判斷是否存在選擇的節點: 使用 if(currentItem == NULL) 條件判斷,如果沒有選擇的節點,則直接返回。
  3. 修改選中節點的文本和圖標: 使用 for 迴圈遍歷節點的所有列,通過 setText 修改每一列的文本為 "Modify" 加上列索引的字元串,通過 setIcon 修改每一列的圖標為特定的圖標。
  4. 記錄操作到 QPlainTextEdit 中: 使用 ui->plainTextEdit->appendPlainText("修改節點名"); 將一行文本記錄添加到 QPlainTextEdit 中,用於記錄操作。

這段代碼的作用是在點擊按鈕時,修改 QTreeWidget 中當前選中節點的文本和圖標,同時在 QPlainTextEdit 中記錄這一修改操作。

void MainWindow::on_pushButton_modifynode_clicked()
{
    // 得到當前節點
    QTreeWidgetItem *currentItem = ui->treeWidget->currentItem();
    if(currentItem == NULL)
        return;
    // 修改選中項
    for(int x=0;x<currentItem->columnCount();x++)
    {
        currentItem->setText(x,tr("Modify") + QString::number(x));
        currentItem->setIcon(x,QIcon(":/image/1.ico"));
    }

    ui->plainTextEdit->appendPlainText("修改節點名");
}

修改節點的執行效果如下圖,當點擊修改選中節點後則將自動替換節點名和圖標信息。

1.5 刪除選中節點

如下槽函數,其核心功能是刪除 QTreeWidget 中當前選中節點,併在 QPlainTextEdit 中添加一行文本記錄。

以下是概述:

  1. 獲取當前選中的節點: 使用 QTreeWidgetItem *currentItem = ui->treeWidget->currentItem(); 獲取當前在 QTreeWidget 中選擇的節點。
  2. 判斷是否存在選擇的節點: 使用 if(currentItem == NULL) 條件判斷,如果沒有選擇的節點,則直接返回。
  3. 判斷是否為頂級父節點: 使用 if(currentItem->parent() == NULL) 條件判斷,如果當前節點沒有父節點(即為頂級父節點),則使用 ui->treeWidget->takeTopLevelItem 刪除該節點。
  4. 如果有父節點,使用父節點的 takeChild 刪除子節點: 使用 delete currentItem->parent()->takeChild(ui->treeWidget->currentIndex().row()); 刪除當前節點。這種情況下,要使用父節點的 takeChild 方法,因為直接刪除會導致父節點無法正確管理子節點。
  5. 記錄操作到 QPlainTextEdit 中: 使用 ui->plainTextEdit->appendPlainText("刪除一個節點"); 將一行文本記錄添加到 QPlainTextEdit 中,用於記錄操作。

這段代碼的作用是在點擊按鈕時,刪除 QTreeWidget 中當前選中的節點,並記錄這一刪除操作到 QPlainTextEdit 中。

void MainWindow::on_pushButton_delnode_clicked()
{
    QTreeWidgetItem *currentItem = ui->treeWidget->currentItem();
    if(currentItem == NULL)
        return;

    // 如果沒有父節點則直接刪除
    if(currentItem->parent() == NULL)
    {
        delete ui->treeWidget->takeTopLevelItem(ui->treeWidget->currentIndex().row());
        std::cout << ui->treeWidget->currentIndex().row() << std::endl;
    }
    else
    {
        // 如果有父節點就要用父節點的takeChild刪除節點
        delete currentItem->parent()->takeChild(ui->treeWidget->currentIndex().row());
    }

    ui->plainTextEdit->appendPlainText("刪除一個節點");
}

刪除節點有兩種情況,如果只有父節點那麼可以直接刪除,如果有子節點則那就要一併刪除,如下圖;

1.6 枚舉全部節點

如下槽函數,其核心功能是遍歷 QTreeWidget 中的所有節點,並輸出每個節點的文本。

以下是概述:

  1. 獲取全部的根節點數量: 使用 int size = ui->treeWidget->topLevelItemCount(); 獲取頂級父節點的數量。
  2. 遍歷所有根節點: 使用 for 迴圈遍歷每一個根節點,通過 ui->treeWidget->topLevelItem(x) 獲取當前的根節點。
  3. 輸出所有根節點: 使用 child->text(0).toStdString().data() 輸出當前根節點的文本信息,並將其輸出到標準輸出流。
  4. 遍歷根節點下的子節點: 使用內層 for 迴圈遍歷當前根節點下的所有子節點,通過 child->child(y) 獲取子節點。
  5. 輸出子節點: 使用 grandson->text(0).toStdString().data() 輸出當前子節點的文本信息,並將其輸出到標準輸出流。
  6. 記錄操作到 QPlainTextEdit 中: 使用 ui->plainTextEdit->appendPlainText("枚舉所有節點"); 將一行文本記錄添加到 QPlainTextEdit 中,用於記錄操作。

這段代碼的作用是在點擊按鈕時,遍歷 QTreeWidget 中的所有節點,輸出每個節點的文本信息,並將信息記錄到 QPlainTextEdit 中。

void MainWindow::on_pushButton_enumnode_clicked()
{
    // 獲取到全部的根節點數量
    int size = ui->treeWidget->topLevelItemCount();
    QTreeWidgetItem *child;
    for(int x=0;x<size;x++)
    {
        // 輸出所有父節點
        child = ui->treeWidget->topLevelItem(x);
        std::cout << "all root = "<< child->text(0).toStdString().data() << std::endl;

        // 得到所有子節點計數
        int childCount = child->childCount();
        // std::cout << "all child count = " << childCount << std::endl;

        // 輸出根節點下麵的子節點
        for(int y=0;y<childCount;++y)
        {
            QTreeWidgetItem *grandson = child->child(y);
            std::cout << "--> sub child = "<< grandson->text(0).toStdString().data() << std::endl;

            ui->plainTextEdit->appendPlainText(grandson->text(0).toStdString().data());
        }
    }

    ui->plainTextEdit->appendPlainText("枚舉所有節點");
}

枚舉所有節點會將父節點與子節點一併輸出,如下圖;

1.7 枚舉選中節點

如下槽函數,其核心功能是遍歷 QTreeWidget 中的所有節點,並輸出每個選中節點的文本信息。

以下是概述:

  1. 獲取全部的根節點數量: 使用 int size = ui->treeWidget->topLevelItemCount(); 獲取頂級父節點的數量。
  2. 遍歷所有根節點: 使用 for 迴圈遍歷每一個根節點,通過 ui->treeWidget->topLevelItem(x) 獲取當前的根節點。
  3. 遍歷根節點下的子節點: 使用內層 for 迴圈遍歷當前根節點下的所有子節點,通過 child->child(y) 獲取子節點。
  4. 判斷是否選中: 使用 if(Qt::Checked == grandson->checkState(0)) 判斷當前子節點是否被選中。
  5. 輸出選中節點信息: 如果子節點被選中,輸出當前根節點與子節點的文本信息,並將信息輸出到標準輸出流。
  6. 記錄操作到 QPlainTextEdit 中: 使用 ui->plainTextEdit->appendPlainText("枚舉所有選中節點"); 將一行文本記錄添加到 QPlainTextEdit 中,用於記錄操作。

這段代碼的作用是在點擊按鈕時,遍歷 QTreeWidget 中的所有節點,輸出每個被選中節點的文本信息,並將信息記錄到 QPlainTextEdit 中。

void MainWindow::on_pushButton_enumselectnode_clicked()
{
    // 獲取到全部的根節點數量
    int size = ui->treeWidget->topLevelItemCount();
    QTreeWidgetItem *child;
    for(int x=0;x<size;x++)
    {
        // 輸出所有父節點
        child = ui->treeWidget->topLevelItem(x);

        // 得到所有子節點計數
        int childCount = child->childCount();

        // 輸出根節點下麵的子節點
        for(int y=0;y<childCount;++y)
        {
            QTreeWidgetItem *grandson = child->child(y);
            // 判斷是否選中,如果選中輸出父節點與子節點
            if(Qt::Checked == grandson->checkState(0))
            {
                std::cout << "root -> " << child->text(0).toStdString().data()
                          << "--> sub child = "<< grandson->text(0).toStdString().data() << std::endl;

                ui->plainTextEdit->appendPlainText(child->text(0).toStdString().data());
                ui->plainTextEdit->appendPlainText(grandson->text(0).toStdString().data());
            }
        }
    }

    ui->plainTextEdit->appendPlainText("枚舉所有選中節點");
}

枚舉所有選中的節點,此處需要打上對勾才會生效,如下圖;

1.8 獲取節點父節點

如下槽函數,其核心功能是獲取當前選中節點的父節點(如果存在),輸出父節點的序號和名字,並將信息記錄到 QPlainTextEdit 中。

以下是概述:

  1. 獲取當前選中節點的父節點: 使用 QTreeWidgetItem *currentItem = ui->treeWidget->currentItem()->parent(); 獲取當前選中節點的父節點。
  2. 獲取父節點在頂級節點中的序號: 使用 int root_count = ui->treeWidget->indexOfTopLevelItem(currentItem); 獲取父節點在頂級節點中的序號。
  3. 判斷是否存在父節點: 使用 if(root_count != -1) 條件判斷,如果存在父節點,執行下麵的操作;否則,直接返回。
  4. 獲取指定序號對應的父節點: 使用 child = ui->treeWidget->topLevelItem(root_count); 獲取指定序號對應的父節點。
  5. 輸出父節點的序號和名字: 使用 std::cout << "root Count = " << root_count << std::endl; 輸出父節點在頂級節點中的序號,以及 std::cout << "root name= "<< child->text(0).toStdString().data() << std::endl; 輸出父節點的名字。
  6. 記錄操作到 QPlainTextEdit 中: 使用 ui->plainTextEdit->appendPlainText("獲取父節點ID"); 將一行文本記錄添加到 QPlainTextEdit 中,用於記錄操作。

這段代碼的作用是在點擊按鈕時,獲取當前選中節點的父節點(如果存在),輸出父節點在頂級節點中的序號和名字,並將信息記錄到 QPlainTextEdit 中。

void MainWindow::on_pushButton_getnode_clicked()
{
    // 取所有的父節點
    QTreeWidgetItem *currentItem = ui->treeWidget->currentItem()->parent();
    int root_count = ui->treeWidget->indexOfTopLevelItem(currentItem);
    std::cout << "root Count = " <<  root_count << std::endl;
    if(root_count != -1)
    {
        // 指定序號對應的父節點名字
        QTreeWidgetItem *child;

        child = ui->treeWidget->topLevelItem(root_count);
        std::cout << "root name= "<< child->text(0).toStdString().data() << std::endl;

        ui->plainTextEdit->appendPlainText(child->text(0).toStdString().data());
    }

    ui->plainTextEdit->appendPlainText("獲取父節點ID");
}

當用戶選中一個子節點時,可通過該槽函數獲取其父節點的ID編號,如下圖;

1.9 綁定右鍵菜單

在開發中我們經常會把它當作一個升級版的ListView組件使用,因為ListView每次只能顯示一列數據集,而使用TableWidget組件顯示多列顯得不夠美觀,此時使用TreeWidget組件顯示單層結構是最理想的方式,同時該組件同樣支持增加右鍵菜單,在真正的開發中尤為常用。

首先我們在MainWindow主窗體中只保留一個treeWidget組件,接著直接來到MainWindow構造函數上,在該函數中我們通過動態創建一個menuBar()並將其隱藏起來,接著將菜單屬性與treeWidget中的事件相互綁定,最後初始化填充一些測試數據,其代碼如下;

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // -------------------------------------------------
    // 初始化組件菜單
    // -------------------------------------------------

    // 在MainWindow中使用右擊菜單需要添加此項
    ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);

    // 創建基礎頂部菜單
    QMenuBar *bar = menuBar();
    this->setMenuBar(bar);
    QMenu * fileMenu = bar->addMenu("菜單1");

    // 實現只隱藏菜單1其他的不受影響
    fileMenu->menuAction()->setVisible(false);

    // 添加子菜單
    GetColumnAction = fileMenu->addAction("獲取列號");
    GetRowDataAction = fileMenu->addAction("獲取本行數據");
    GetLineAction = fileMenu->addAction("獲取行號");

    // 分別設置圖標
    GetColumnAction->setIcon(QIcon(":/image/1.ico"));
    GetRowDataAction->setIcon(QIcon(":/image/2.ico"));
    GetLineAction->setIcon(QIcon(":/image/3.ico"));

    // 為子菜單綁定熱鍵
    GetColumnAction->setShortcut(Qt::CTRL | Qt::Key_A);
    GetRowDataAction->setShortcut(Qt::SHIFT | Qt::Key_S);
    GetLineAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_B);

    // -------------------------------------------------
    // 綁定槽函數
    // -------------------------------------------------

    // 綁定槽函數: 獲取選中列
    connect(GetColumnAction,&QAction::triggered,this,[=](){
        int col = ui->treeWidget->currentColumn();
        std::cout << col << std::endl;
    });

    // 綁定槽函數: 獲取選中的第0行的數據內容
    connect(GetRowDataAction,&QAction::triggered,this,[=](){
        QString msg = ui->treeWidget->currentItem()->text(0);
        std::cout << msg.toStdString().data() << std::endl;
    });

    // 綁定槽函數: 獲取當前選中的索引值
    connect(GetLineAction,&QAction::triggered,this,[=](){
        int row  = ui->treeWidget->currentIndex().row();
        std::cout << row << std::endl;
    });

    // -------------------------------------------------
    // 設置屬性填充數據
    // -------------------------------------------------

    // 設置treeWidget屬性
    ui->treeWidget->setColumnCount(4);         // 設置總列數
    ui->treeWidget->setColumnWidth(0,300);     // 設置最後一列寬度自適應
    ui->treeWidget->setIndentation(1);         // 設置表頭縮進為1

    // 設置表頭數據
    QStringList headers;
    headers.append("文件名");
    headers.append("更新時間");
    headers.append("文件類型");
    headers.append("文件大小");
    ui->treeWidget->setHeaderLabels(headers);

    // 模擬插入數據到表中
    for(int x=0;x<100;x++)
    {
        QTreeWidgetItem* item=new QTreeWidgetItem();
        item->setText(0,"《LyShark 從入門到精通》");
        item->setIcon(0,QIcon(":/image/1.ico"));
        item->setText(1,"2023-12-17");
        item->setText(2,"*.pdf");
        item->setText(3,"102MB");
        item->setIcon(3,QIcon(":/image/2.ico"));
        ui->treeWidget->addTopLevelItem(item);
    }
}

此時,當treeWidget中的右鍵被點擊後則將觸發on_treeWidget_customContextMenuRequested槽函數,此函數中動態的新建一個菜單,併在滑鼠點擊位置將其顯示輸出,代碼如下;

// 當treeWidget中的右鍵被點擊時則觸發
void MainWindow::on_treeWidget_customContextMenuRequested(const QPoint &pos)
{
    std::cout << "x pos = "<< pos.x() << "y pos = " << pos.y() << std::endl;
    Q_UNUSED(pos);

    // 新建Menu菜單
    QMenu *ptr = new QMenu(this);

    // 添加Actions創建菜單項
    ptr->addAction(GetColumnAction);
    ptr->addAction(GetLineAction);

    // 添加一個分割線
    ptr->addSeparator();
    ptr->addAction(GetRowDataAction);

    // 在滑鼠游標位置顯示右鍵快捷菜單
    ptr->exec(QCursor::pos());
    // 手工創建的指針必須手工刪除
    delete ptr;
}

運行後讀者可看到如下圖所示的輸出效果;

完整案例下載

文章出處:https://www.cnblogs.com/LyShark/p/17908946.html
本博客所有文章除特別聲明外,均採用 BY-NC-SA 許可協議。轉載請註明出處!
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、定義 義一個對象來封裝一系列的對象交互。中介者模式使各對象不需要顯示地相互引用,從而使其耦合鬆散,而且可以讓你相對獨立地改變它們之間的交互。中介者模式又稱為調停模式,它是一種對象說行為型模式。 二、描述 在中介者模式中,引入了用於協調其他對象/類之間的相互調用的中介者類,為了讓系統具有更好的靈活 ...
  • C-08 聚合(分組)函數和SQL(DQL)執行流程 上一章,講到了SQL單行函數。實際上SQL函數還有一類,叫做聚合函數,或者多行,分組函數,它是對一組數據進行彙總的函數,輸入的是一組數據的集合,輸出的是單個值。 1.聚合函數的介紹 什麼是聚合函數 聚合函數作用於一組數據,並對一組數據返回一個值。 ...
  • 如題,這是一個很簡單也很基礎的問題,先看不同操作的結果有什麼不同 結果1:項目下出現了一個空“文件夾” 結果2:項目下多了一個“Python Package”,該package下包含了一個“__init__.py”文件,該py文件是空的 如果把該py文件刪掉後,package也就變成了directo ...
  • 1 數據可視化 自 DataGrip 2023.3 發佈以來,已整合 Lets-Plot 庫,實現數據可視化。該可視化功能可用於所有三種類型的網格: 主選項卡:在打開表、視圖或 CSV 文件時,在分割模式下顯示圖表。 結果選項卡:在 服務 工具視窗中觀察查詢結果時,可以顯示圖表而不是網格。 編輯器中 ...
  • 在Java中,我們經常需要獲取某個類的Class對象,以便進行反射操作、動態載入類或者獲取類的信息。本文將介紹Java中獲取Class對象的三種常見方式。 1. 使用.class語法 獲取Class對象最簡單的方式就是使用.class語法。每個Java類都有一個隱含的靜態成員變數class,可以通過 ...
  • C 語言中的類型轉換 有時,您必須將一種數據類型的值轉換為另一種類型。這稱為類型轉換 隱式轉換 當您將一種類型的值分配給另一種類型的變數時,編譯器會自動進行隱式轉換。 例如,如果您將一個 int 值分配給一個 float 類型: // 自動轉換:int to float float myFloat ...
  • 為什麼需要熱載入 在某些情況,你可能不希望關閉Python進程並重新打開,或者你無法重新啟動Python,這時候就需要實現實時修改代碼實時生效,而不用重新啟動Python 在我的需求下,這個功能非常重要,我將Python註入到了其他進程,並作為一個線程運行。如果我想關閉Python,要麼殺死Pyth ...
  • 哈嘍大家好,我是鹹魚 我們知道 Python 是一門具有動態特性的語言,在編寫 Python 代碼的時候不需要顯式地指定變數的類型 這樣做雖然方便,但是降低了代碼的可閱讀性,在後期 review 代碼的時候容易對變數的類型產生混淆,需要查閱大量上下文,導致後期維護困難 為了提高代碼的可讀性、可維護性 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...