1. 程式人生 > >Qt樹形控制元件QTreeView使用1——節點的新增刪除操作 複選框的設定

Qt樹形控制元件QTreeView使用1——節點的新增刪除操作 複選框的設定

通過QStandardItem和QStandardItemModel可以很簡單方便的給QTreeView新增節點,但是,許多樹形控制元件都需要樹的節點需要一個複選框(checkBox),網上許多資料都是通過自定義model來實現的,而且不能很好的實現checkbox的父子關聯(父節點選中子節點全部選中,父節點不選,子節點全部選),下面將介紹如何使用QStandardItem和QStandardItemModel實現複選框,且實現父子關聯


1.使用QStandardItem使樹形控制元件條目帶上覆選框

複選框在樹形控制元件中經常見到,在QStandardItem中已經封裝好了對複選框的一些設定
  1. void
     QStandardItem:: setCheckable ( bool checkable )  
  2. void QStandardItem:: setTristate ( bool tristate )  
  3. void QStandardItem:: setCheckState ( Qt::CheckState state )  
  4. Qt::CheckState QStandardItem:: checkState () const
  5. bool QStandardItem:: isCheckable () const
  6. bool QStandardItem:: isTristate () const

從字面意思就知道這些函式是幹什麼的了,但這裡要注意一些,checkBox有兩種情況, 一種是兩態,就是選中和不選中 一種是三態,選中、不選中、不完全選中,如圖:
這種三態叫Tristate。 要設定條目有複選框只需要使用QStandardItem的函式setCheckable,無論是兩態還是三態都需要先setCheckable,setCheckable預設是兩態,如果希望是三態的話,需要再setTristate 示例程式碼如下:(樹形檢視節點的具體新增方法見上篇文章)
  1. QStandardItemModel* model = new
     QStandardItemModel(ui->treeView);  
  2. model->setHorizontalHeaderLabels(QStringList()<<QStringLiteral("專案名")<<QStringLiteral("資訊"));  
  3. QStandardItem* itemProject = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_Project")],QStringLiteral("專案"));  
  4. model->appendRow(itemProject);  
  5. model->setItem(model->indexFromItem(itemProject).row(),1,new QStandardItem(QStringLiteral("專案資訊說明")));  
  6. QStandardItem* itemFolder = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_folder")],QStringLiteral("資料夾1"));  
  7. itemProject->appendRow(itemFolder);  
  8. itemProject->setChild(itemFolder->index().row(),1,new QStandardItem(QStringLiteral("資訊說明")));  
  9. itemFolder = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_folder")],QStringLiteral("資料夾2"));  
  10. itemProject->appendRow(itemFolder);  
  11. for(int i=0;i<5;++i){  
  12.     QStandardItem* itemgroup = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_group")],QStringLiteral("組%1").arg(i+1));  
  13.     itemFolder->appendRow(itemgroup);  
  14.     for(int j=0;j<(i+1);++j){  
  15.         QStandardItem* itemchannel = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_channel")],QStringLiteral("頻道%1").arg(j+1));  
  16.         itemgroup->appendRow(itemchannel);  
  17.         itemgroup->setChild(itemchannel->index().row(),1,new QStandardItem(QStringLiteral("頻道%1資訊說明").arg(j+1)));  
  18.     }  
  19. }  
  20. itemProject->setChild(itemFolder->index().row(),1,new QStandardItem(QStringLiteral("資料夾2資訊說明")));  
  21. itemProject = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_Project")],QStringLiteral("專案2"));  
  22. model->appendRow(itemProject);  
  23. for(int i =0;i<3;++i)  
  24. {  
  25.     itemFolder = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_folder")],QStringLiteral("專案2資料夾%1").arg(i+1));  
  26.     itemFolder->setCheckable(true);  
  27.     itemFolder->setTristate(true);  
  28.     QStandardItem* itemFolderDes = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_group")],QStringLiteral("資料夾%1組").arg(i+1));  
  29.     itemProject->appendRow(itemFolder);  
  30.     itemProject->setChild(itemFolder->index().row(),1,itemFolderDes);  
  31.     for(int j=0;j<i+1;++j)  
  32.     {  
  33.          QStandardItem* item = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_dataItem")],QStringLiteral("專案%1").arg(j+1));  
  34.          item->setCheckable(true);  
  35.          itemFolder->appendRow(item);  
  36.     }  
  37. }  
  38. //關聯專案屬性改變的訊號和槽
  39. connect(model,&QStandardItemModel::itemChanged,this,&Widget::treeItemChanged);  
  40. //connect(model,SIGNAL(itemChanged(QStandardItem*)),this,SLOT(treeItemChanged(QStandardItem*)));
  41. ui->treeView->setModel(model);  


程式碼中m_publicIconMap是QMap<QString,QIcon>物件,用於存放定義好的圖示,在樹形檢視節點新增之前進行初始化,初始化程式碼如下:
  1. m_publicIconMap[QStringLiteral("treeItem_Project")] = QIcon(QStringLiteral(":/treeItemIcon/res_treeItemIcon/Project.png"));  
  2. m_publicIconMap[QStringLiteral("treeItem_folder")] = QIcon(QStringLiteral(":/treeItemIcon/res_treeItemIcon/folder.png"));  
  3. m_publicIconMap[QStringLiteral("treeItem_folder-ansys")] = QIcon(QStringLiteral(":/treeItemIcon/res_treeItemIcon/folder-ansys.png"));  
  4. m_publicIconMap[QStringLiteral("treeItem_group")] = QIcon(QStringLiteral(":/treeItemIcon/res_treeItemIcon/group.png"));  
  5. m_publicIconMap[QStringLiteral("treeItem_channel")] = QIcon(QStringLiteral(":/treeItemIcon/res_treeItemIcon/channel.png"));  

效果圖:

2.三態複選框的智慧關聯

三態複選框的主要體現就在樹形控制元件裡,如果子專案全選,父級需要全選,如果子專案部分選,父級就是不完全選 下圖是三態的正確表現方法
但QTreeView在QStandardItem設定複選框後,並不是按照規則的,這時需要進行程式碼設定

2.1 捕獲複選框改變的訊號

要對複選框進行操作,首先需要捕獲樹形檢視的複選框改變發出的訊號 通過QStandardItemModel設定的專案,任何改變都會觸發void QStandardItemModel::itemChanged( * item)訊號 因此需要定義一個槽函式和這個訊號關聯
  1. private slots :  
  2. void treeItem_CheckChildChanged ( QStandardItem * item );  


關聯程式碼寫在model建立之後的地方:
  1. //關聯專案屬性改變的訊號和槽
  2. connect ( model ,&QStandardItemModel::itemChanged , this ,&Widget::treeItemChanged );  
  3. //connect(model,SIGNAL(itemChanged(QStandardItem*)),this,SLOT(treeItemChanged(QStandardItem*)));

這裡使用最新的訊號和槽的關聯方法,記得在pro檔案中加入如下,使得支援C++11 CONFIG+=c++11 槽函式的寫法如下: void Widget :: treeItemChanged ( QStandardItem * item )
{
} 下面開始實現三態的自動關聯(父子節點checkbox自動關聯)

2.2 父子節點複選框自動關聯實現

  1. void Widget : : treeItemChanged ( QStandardItem * item )  
  2. {  
  3.     if ( item == nullptr )  
  4.     return ;  
  5.     if ( item - > isCheckable ())  
  6.     {  
  7.         //如果條目是存在複選框的,那麼就進行下面的操作
  8.         Qt : : CheckState state = item - > checkState (); //獲取當前的選擇狀態
  9.         if ( item - > isTristate ())  
  10.         {  
  11.              //如果條目是三態的,說明可以對子目錄進行全選和全不選的設定
  12.             if ( state != Qt : : PartiallyChecked )  
  13.             {  
  14.                 //當前是選中狀態,需要對其子專案進行全選
  15.                 treeItem_checkAllChild ( item , state == Qt : : Checked ? true : false );  
  16.             }  
  17.         }  
  18.         else
  19.         {  
  20.             //說明是兩態的,兩態會對父級的三態有影響
  21.             //判斷兄弟節點的情況
  22.             treeItem_CheckChildChanged ( item );  
  23.         }  
  24.     }  
  25. }  


首先要判斷條目的狀態,如果條目是有複選框的話,那麼就進行操作。通過函式isCheckable()可以判斷條目是否有複選框 在確認條目有複選框後,需要獲取當前條目的選中狀態,使用checkState ()函式可以判斷當前條目的選中狀態; 現在分兩種情況: 1.如果條目是三態的,說明要判斷它的子節點。條目選中時,所有子節點都將選中,條目不選中時,所有子節點都不選中 2.如果條目是兩態的,說明可能會影響它的三態的父節點,當兩態節點選中且其所有的兄弟節點都選中,三態父節點選中,若兩態子節點和其兄弟節點都沒選中,那麼其三態父節點將不選中,若果兄弟節點有選中有不選中,三態父節點將是處於不完全選中狀態

2.2.1 子節點遞迴全選

treeItem_checkAllChild 函式是用於使子節點全選的函式。這個函式實現如下:
  1. ///
  2. /// \brief 遞迴設定所有的子專案為全選或全不選狀態
  3. /// \param item 當前專案
  4. 相關推薦

    Qt樹形控制元件QTreeView使用1——節點新增刪除操作 設定

    通過QStandardItem和QStandardItemModel可以很簡單方便的給QTreeView新增節點,但是,許多樹形控制元件都需要樹的節點需要一個複選框(checkBox),網上許多資料都是通過自定義model來實現的,而且不能很好的實現checkbox的父子關聯(父節點選中子節點全部選中

    QT tableview控制元件Item中新增文字和控制元件

    實現方法: 自定義tableview 的delegate 在paint函式中,將原來的option中的rect切分為 文字顯示 和 按鈕繪製兩部分; 在editorevent中,實現按鈕事件響應。 //繪製文字 intiTextRight=option.rect.righ

    element-ui樹形控制元件,子節點選擇時預設將父節點上傳解決方法

    用element的樹形控制元件實現許可權管理的時候碰到一個問題,當一項大許可權節點下的小許可權節點被選中時,大節點屬於半選狀態,但是最後輸出的結果不包含大節點的id 這樣會導致兩個問題 首先第一次選擇時,傳給後端的許可權列表不包含大的許可權id 回顯時,如果

    vue中element-ui 樹形控制元件-樹節點的選擇(選中當前節點,獲取當前id並且獲取其父級id)

    Element-ui官網給的方法 getCheckedKeys() { console.log(this.$refs.tree.getCheckedKeys()); }, 這種只有在所有子級都被選中的情況下才能獲得父級的id,如果不選中所有的子級那麼獲取得到的

    QT重寫控制元件函式並新增滑鼠單擊事件

    重寫QComboBox類 1.在工程中新建一個C++類,命名為myboBox,base的地方填寫QComboBox,緊接著勾選#include QWidget。 2.myboBox檔案中包含標頭檔案#include <QComboBox>嗎,並新增Q_OBJEC

    Qt 禁止控制元件內容被 複製 貼上 剪貼 全

    我們知道,在某些時候,控制元件的內容是保密的,比如登入密碼,除了讓這些控制元件的內容不可見(以黑色圓圈、星號的形式顯示),還應該讓該控制元件的內容禁止被複制 貼上 剪貼 全選等。 1.控制元件的內容不可見 即密碼模式,這個簡單 lineEdit-&g

    C#開發學習筆記:向Dev控制元件庫中的GridControl新增自定義

    <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">Dev控制元件庫自帶的有複選框列,預設是不顯示狀態,如果需要則設定相關

    input控制元件的checkbox屬性自定義勾

    思路 首先隱藏input預設勾選框 通過繫結label標籤,設定label的樣式來設定勾選框 效果 程式碼 # html中input的checkbox定義,使用for迴圈建立多個checkbox並繫結到label上 <div class="tab_1

    VUE餓了麼樹形控制元件新增增刪改功能

    轉自:https://segmentfault.com/a/1190000011574698#articleHeader2 element-ui樹形控制元件:地址 在原文件中有個案例是有新增和刪除功能,但是後來發現其修改的資料並不能直接影響到樹形資料,所以採用了 rende

    vue elementUI tree樹形控制元件如何獲取父節點ID

    首先找到element-ui.common.js檔案 如下 具體看你工程下的node_modulesD:\workSpace\vue_manage\node_modules\element-ui\lib\element-ui.common.js找到getCheckedNode

    Javascript、jQuery 操作select控制元件大全(新增、修改、刪除、選中、清空、判斷存在等)

     1 判斷select選項中是否存在Value="paraValue"的Item   2 向select選項中加入一個Item   3從select選項中刪除一個Item   4刪除select中選中的項   5修改select選項中 value="paraValue"的t

    QT獲取控制元件的內容去傳參的小發現

    1://處理文字框(內容是一個連續的字串)的方法(不能直接用文字框的內容去傳參,//否則會有意想不到的錯誤發生,需要利用先拷貝到陣列,然後利用陣列去傳參), #include <QStringList> #include <QString> int arg

    qt控制元件之textEdit

    獲取 textedit 的文字內容:QString text = ui->textEdit->toPlainText(); 設定textedit 的文字內容:ui->textEdit->append(“lkf”);此方法追加內容是換行追加 char b[10]

    金蝶bos 自定義UI介面新增控制元件,並且做業務處理

     /**      * 顯示工程型別      * @author daihao      * 

    iOS開發UI篇——一個可擴充套件性極強的樹形控制元件

    一、簡介 樹形控制元件在多列列表、多級選單中使用比較常見,比如:國家-省份-城市 多級選擇、學校-專業-班級 多級選擇等等。然而IOS自帶控制元件中並不存在樹形控制元件,我們要在IOS開發中使用樹形控制元件,通常需要自己擴充套件UITableView列表控制元件。現在在這裡開源一個自己寫的高擴充套件性,高複用

    iOS開發UI篇--一個可擴充套件性極強的樹形控制元件

    一、簡介 樹形控制元件在多列列表、多級選單中使用比較常見,比如:國家-省份-城市 多級選擇、學校-專業-班級 多級選擇等等。然而IOS自帶控制元件中並不存在樹形控制元件,我們要在IOS開發中使用樹形控制元件,通常需要自己擴充套件UITableView列表控制元件。現在在這裡開源一個自己寫的高擴充套件性,高複

    BCGControlBar教程:如何將MFC控制元件的BCGControlBarBCGSuite新增到對話方塊中

    BCGControlBar Pro for MFC最新試用版下載請猛戳>>> 如果您正在使用我們的Windows窗體產品,那麼將我們的控制元件新增到窗體是沒有問題的:只需從Visual Studio工具箱中拖動所需的專案並將其放入窗體即可。在對話方塊中新增非標準控制元件需要一些

    Qt編寫控制元件時遇到underMouse判斷錯誤的情況(誤判State_MouseOver)

    在寫qt下的ribbon控制元件時,重繪了一個toolbutton,但是卻遇到一個問題就是在有彈出選單模式下,點選選單後按鈕還處於hover狀態,什麼意思,就是如圖所示: 原始碼見:https://github.com/czyt1988/SARibbon/blob/master

    elementui 後臺管理系統遇到的問題(二) 樹形控制元件 el-tree

    elementui中樹形控制元件的使用 一、將後臺返回的資料填充到前端控制元件中,需要注意的幾點問題 (1)、el-tree中需要繫結node-key='自定義的id名稱' (2)、在配置data中defaultProps中的屬性時,要按照與後端協商的欄位名稱對稱 (3)、重要的是要月後端協商返回欄位內容

    遞迴組裝Cascader 級聯選擇器和Tree 樹形控制元件結構的資料

    以商品分類表為例,重點看分類ID和父分類ID public List<Map<String,Object>> getGoodsCategoryTree() { //1.獲取所有商品分類,條件:category_id!=0(0為頂級選單的父類I