乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Qt樹形控件QTreeView使用2

       gastonfeng 2016-02-14
      這種三態(tài)叫Tristate。
      要設(shè)置條目有復(fù)選框只需要使用QStandardItem的函數(shù)setCheckable,無論是兩態(tài)還是三態(tài)都需要先setCheckable,setCheckable默認(rèn)是兩態(tài),如果希望是三態(tài)的話,需要再setTristate
      示例代碼如下:(樹形視圖節(jié)點(diǎn)的具體添加方法見上篇文章)
      1. QStandardItemModel* model = new QStandardItemModel(ui->treeView);  
      2. model->setHorizontalHeaderLabels(QStringList()<<><>< li=""><><>
      3. QStandardItem* itemProject = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_Project")],QStringLiteral("項(xiàng)目"));  
      4. model->appendRow(itemProject);  
      5. model->setItem(model->indexFromItem(itemProject).row(),1,new QStandardItem(QStringLiteral("項(xiàng)目信息說明")));  
      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("項(xiàng)目2"));  
      22. model->appendRow(itemProject);  
      23. for(int i =0;i<3;++i)  
      24. {  
      25.     itemFolder = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_folder")],QStringLiteral("項(xiàng)目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<>< li=""><>
      32.     {  
      33.          QStandardItem* item = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_dataItem")],QStringLiteral("項(xiàng)目%1").arg(j+1));  
      34.          item->setCheckable(true);  
      35.          itemFolder->appendRow(item);  
      36.   
      37.     }  
      38. }  
      39. //關(guān)聯(lián)項(xiàng)目屬性改變的信號(hào)和槽  
      40. connect(model,&QStandardItemModel::itemChanged,this,&Widget::treeItemChanged);  
      41. //connect(model,SIGNAL(itemChanged(QStandardItem*)),this,SLOT(treeItemChanged(QStandardItem*)));  
      42. ui->treeView->setModel(model);  


      代碼中m_publicIconMap是QMap對(duì)象,用于存放定義好的圖標(biāo),在樹形視圖節(jié)點(diǎn)添加之前進(jìn)行初始化,初始化代碼如下:
      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.三態(tài)復(fù)選框的智能關(guān)聯(lián)

      三態(tài)復(fù)選框的主要體現(xiàn)就在樹形控件里,如果子項(xiàng)目全選,父級(jí)需要全選,如果子項(xiàng)目部分選,父級(jí)就是不完全選
      下圖是三態(tài)的正確表現(xiàn)方法



      但QTreeView在QStandardItem設(shè)置復(fù)選框后,并不是按照規(guī)則的,這時(shí)需要進(jìn)行代碼設(shè)置

      2.1 捕獲復(fù)選框改變的信號(hào)

      要對(duì)復(fù)選框進(jìn)行操作,首先需要捕獲樹形視圖的復(fù)選框改變發(fā)出的信號(hào)
      通過QStandardItemModel設(shè)置的項(xiàng)目,任何改變都會(huì)觸發(fā)void QStandardItemModel::itemChanged(QStandardItem * item)信號(hào)
      因此需要定義一個(gè)槽函數(shù)和這個(gè)信號(hào)關(guān)聯(lián)
      1. private slots :  
      2. void treeItem_CheckChildChanged ( QStandardItem * item );  


      關(guān)聯(lián)代碼寫在model創(chuàng)建之后的地方:
      1. //關(guān)聯(lián)項(xiàng)目屬性改變的信號(hào)和槽  
      2. connect ( model ,&QStandardItemModel::itemChanged , this ,&Widget::treeItemChanged );  
      3. //connect(model,SIGNAL(itemChanged(QStandardItem*)),this,SLOT(treeItemChanged(QStandardItem*)));  

      這里使用最新的信號(hào)和槽的關(guān)聯(lián)方法,記得在pro文件中加入如下,使得支持C++11
      CONFIG+=c++11
      槽函數(shù)的寫法如下:
      void Widget :: treeItemChanged ( QStandardItem * item )
      {
      }

      下面開始實(shí)現(xiàn)三態(tài)的自動(dòng)關(guān)聯(lián)(父子節(jié)點(diǎn)checkbox自動(dòng)關(guān)聯(lián))

      2.2 父子節(jié)點(diǎn)復(fù)選框自動(dòng)關(guān)聯(lián)實(shí)現(xiàn)

      1. void Widget : : treeItemChanged ( QStandardItem * item )  
      2. {  
      3.     if ( item == nullptr )  
      4.     return ;  
      5.     if ( item - > isCheckable ())  
      6.     {  
      7.         //如果條目是存在復(fù)選框的,那么就進(jìn)行下面的操作  
      8.         Qt : : CheckState state = item - > checkState (); //獲取當(dāng)前的選擇狀態(tài)  
      9.         if ( item - > isTristate ())  
      10.         {  
      11.              //如果條目是三態(tài)的,說明可以對(duì)子目錄進(jìn)行全選和全不選的設(shè)置  
      12.             if ( state != Qt : : PartiallyChecked )  
      13.             {  
      14.                 //當(dāng)前是選中狀態(tài),需要對(duì)其子項(xiàng)目進(jìn)行全選  
      15.                 treeItem_checkAllChild ( item , state == Qt : : Checked ? true : false );  
      16.             }  
      17.         }  
      18.         else  
      19.         {  
      20.             //說明是兩態(tài)的,兩態(tài)會(huì)對(duì)父級(jí)的三態(tài)有影響  
      21.             //判斷兄弟節(jié)點(diǎn)的情況  
      22.             treeItem_CheckChildChanged ( item );  
      23.         }  
      24.     }  
      25. }  


      首先要判斷條目的狀態(tài),如果條目是有復(fù)選框的話,那么就進(jìn)行操作。通過函數(shù)isCheckable()可以判斷條目是否有復(fù)選框
      在確認(rèn)條目有復(fù)選框后,需要獲取當(dāng)前條目的選中狀態(tài),使用checkState ()函數(shù)可以判斷當(dāng)前條目的選中狀態(tài);
      現(xiàn)在分兩種情況:
      1.如果條目是三態(tài)的,說明要判斷它的子節(jié)點(diǎn)。條目選中時(shí),所有子節(jié)點(diǎn)都將選中,條目不選中時(shí),所有子節(jié)點(diǎn)都不選中
      2.如果條目是兩態(tài)的,說明可能會(huì)影響它的三態(tài)的父節(jié)點(diǎn),當(dāng)兩態(tài)節(jié)點(diǎn)選中且其所有的兄弟節(jié)點(diǎn)都選中,三態(tài)父節(jié)點(diǎn)選中,若兩態(tài)子節(jié)點(diǎn)和其兄弟節(jié)點(diǎn)都沒選中,那么其三態(tài)父節(jié)點(diǎn)將不選中,若果兄弟節(jié)點(diǎn)有選中有不選中,三態(tài)父節(jié)點(diǎn)將是處于不完全選中狀態(tài)

      2.2.1 子節(jié)點(diǎn)遞歸全選

      treeItem_checkAllChild 函數(shù)是用于使子節(jié)點(diǎn)全選的函數(shù)。這個(gè)函數(shù)實(shí)現(xiàn)如下:

      1. ///  
      2. /// \brief 遞歸設(shè)置所有的子項(xiàng)目為全選或全不選狀態(tài)  
      3. /// \param item 當(dāng)前項(xiàng)目  
      4. /// \param check true時(shí)為全選,false時(shí)全不選  
      5. ///  
      6. void Widget::treeItem_checkAllChild(QStandardItem * item, bool check)  
      7. {  
      8.     if(item == nullptr)  
      9.         return;  
      10.     int rowCount = item->rowCount();  
      11.     for(int i=0;i<>< li=""><>
      12.     {  
      13.         QStandardItem* childItems = item->child(i);  
      14.         treeItem_checkAllChild_recursion(childItems,check);  
      15.     }  
      16.     if(item->isCheckable())  
      17.         item->setCheckState(check ? Qt::Checked : Qt::Unchecked);  
      18. }  
      19. void Widget::treeItem_checkAllChild_recursion(QStandardItem * item,bool check)  
      20. {  
      21.     if(item == nullptr)  
      22.         return;  
      23.     int rowCount = item->rowCount();  
      24.     for(int i=0;i<>< li=""><>
      25.     {  
      26.         QStandardItem* childItems = item->child(i);  
      27.         treeItem_checkAllChild_recursion(childItems,check);  
      28.     }  
      29.     if(item->isCheckable())  
      30.         item->setCheckState(check ? Qt::Checked : Qt::Unchecked);  
      31. }  


      通過這個(gè)功能實(shí)現(xiàn),可以看看如何對(duì)樹形節(jié)點(diǎn)的所有子節(jié)點(diǎn)進(jìn)行遍歷,一般樹形節(jié)點(diǎn)的遍歷是通過遞歸來實(shí)現(xiàn)的(遞歸的效率不是最高的,可以把遞歸拆解為循環(huán))。
      QStandardItem的child方法可以獲取它的下級(jí)子節(jié)點(diǎn),在這個(gè)方法之前現(xiàn)需要查明有多少個(gè)子節(jié)點(diǎn),rowCount()方法是獲取樹形節(jié)點(diǎn)下一級(jí)的子節(jié)點(diǎn)個(gè)數(shù)(在樹形視圖中,每個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)算作這個(gè)節(jié)點(diǎn)的條目,第一個(gè)節(jié)點(diǎn)就是第一行,第二個(gè)就是第二行,以此類推,如果樹形視圖有多列的話,那么列也會(huì)起作用)。
      treeItem_checkAllChild_recursion是個(gè)遞歸函數(shù),通過這個(gè)函數(shù)可以把樹形節(jié)點(diǎn)的所有子節(jié)點(diǎn)遍歷一遍。
      通過上面的這個(gè)方法,即可實(shí)現(xiàn)第一種情況。

      2.2.2 父節(jié)點(diǎn)遞歸處理


      treeItem_CheckChildChanged函數(shù)是用于處理第二種情況的,此函數(shù)主要對(duì)父級(jí)節(jié)點(diǎn)有影響,函數(shù)實(shí)現(xiàn)如下:
      1. ///  
      2. /// \brief 根據(jù)子節(jié)點(diǎn)的改變,更改父節(jié)點(diǎn)的選擇情況  
      3. /// \param item  
      4. ///  
      5. void Widget::treeItem_CheckChildChanged(QStandardItem * item)  
      6. {  
      7.     if(nullptr == item)  
      8.         return;  
      9.     Qt::CheckState siblingState = checkSibling(item);  
      10.     QStandardItem * parentItem = item->parent();  
      11.     if(nullptr == parentItem)  
      12.         return;  
      13.     if(Qt::PartiallyChecked == siblingState)  
      14.     {  
      15.         if(parentItem->isCheckable() && parentItem->isTristate())  
      16.             parentItem->setCheckState(Qt::PartiallyChecked);  
      17.     }  
      18.     else if(Qt::Checked == siblingState)  
      19.     {  
      20.         if(parentItem->isCheckable())  
      21.             parentItem->setCheckState(Qt::Checked);  
      22.     }  
      23.     else  
      24.     {  
      25.         if(parentItem->isCheckable())  
      26.             parentItem->setCheckState(Qt::Unchecked);  
      27.     }  
      28.     treeItem_CheckChildChanged(parentItem);  
      29. }  


      此函數(shù)也是一個(gè)遞歸函數(shù),首先要判斷的是父級(jí)是否到達(dá)頂層,到達(dá)底層作為遞歸的結(jié)束,然后通過函數(shù)checkSibling判斷當(dāng)前的兄弟節(jié)點(diǎn)的具體情況,checkSibling方法的實(shí)現(xiàn)如下:

      1. ///  
      2. /// \brief 測(cè)量兄弟節(jié)點(diǎn)的情況,如果都選中返回Qt::Checked,都不選中Qt::Unchecked,不完全選中返回Qt::PartiallyChecked  
      3. /// \param item  
      4. /// \return 如果都選中返回Qt::Checked,都不選中Qt::Unchecked,不完全選中返回Qt::PartiallyChecked  
      5. ///  
      6. Qt::CheckState Widget::checkSibling(QStandardItem * item)  
      7. {  
      8.     //先通過父節(jié)點(diǎn)獲取兄弟節(jié)點(diǎn)  
      9.     QStandardItem * parent = item->parent();  
      10.     if(nullptr == parent)  
      11.         return item->checkState();  
      12.     int brotherCount = parent->rowCount();  
      13.     int checkedCount(0),unCheckedCount(0);  
      14.     Qt::CheckState state;  
      15.     for(int i=0;i<>< li=""><>
      16.     {  
      17.         QStandardItem* siblingItem = parent->child(i);  
      18.         state = siblingItem->checkState();  
      19.         if(Qt::PartiallyChecked == state)  
      20.             return Qt::PartiallyChecked;  
      21.         else if(Qt::Unchecked == state)  
      22.             ++unCheckedCount;  
      23.         else  
      24.             ++checkedCount;  
      25.         if(checkedCount>0 && unCheckedCount>0)  
      26.             return Qt::PartiallyChecked;  
      27.     }  
      28.     if(unCheckedCount>0)  
      29.         return Qt::Unchecked;  
      30.     return Qt::Checked;  
      31. }  

      checkSibling用于判斷兄弟節(jié)點(diǎn)的關(guān)系,兄弟節(jié)點(diǎn)之間無外乎三種關(guān)系:
      1.全選
      2.全不選
      3.部分選中
      獲取QStandardItem的兄弟節(jié)點(diǎn)有多種方法,這里是通過獲取它的父級(jí)在獲取父級(jí)的子節(jié)點(diǎn)來得到包括它自己的所有兄弟節(jié)點(diǎn),另外QStandardItem可以通過函數(shù)QModelIndex index() const;獲取Item對(duì)應(yīng)的QModelIndex,QModelIndex有QModelIndex QModelIndex::sibling(int row, int column) const方法獲取兄弟節(jié)點(diǎn)。
      通過以上幾個(gè)函數(shù),即可實(shí)現(xiàn)QTreeView的復(fù)選框及自動(dòng)識(shí)別勾選的功能。
      下面放出效果圖:





        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多