Qt QTreeWidget 相關的bug

 

QTreeWidget在添加了數據之後點擊擴展箭頭展開和收縮的時候會顯得卡頓,這個是qt內核的一個bug,正常情況下應該是立即響應的,既然是qt的bug,就只能換種方式實現TreeWidget來解決這個bug,具體辦法大致可以有一下幾種,具體看需求來決定用哪一種方法更好:

  1. 如果需求要求實現的TreeWidget不要求是完全的TreeWidget,擴展的層次是有限制的,就是隻有2層,3層或者4層,需求要求的TreeWidget節點層次比較少有限制,可以使用QListView這樣的空間代替QTreeWidget,只要控制好他們層次的擴展關係,自定義響應的類型是父類型還是子類型等,來控制改顯示的item是應該縮進的大小。如果是子節點就繪製縮進大一點,如果是父節點就讓縮進的小一點,這樣就能用類似QListView做出類似QTreeWidget的效果了

2.還有一種辦法就是還是使用類似QTreeWidget組件,關於這個操作擴展和收縮會卡頓的bug可以隱藏起來,換一種辦法實現。如何隱藏起來呢,QTreeWidget有一個屬性

indentation : int

indentation of the items in the tree view.

This property holds the indentation measured in pixels of the items for each level in the tree view. For top-level items, the indentation specifies the horizontal distance from the viewport edge to the items in the first column; for child items, it specifies their indentation from their parent items.

By default, the value of this property is style dependent. Thus, when the style changes, this property updates from it. Calling setIndentation() stops the updates, calling resetIndentation() will restore default behavior.

這個屬性是專門用於處理QTreeWidget的item縮進的,item層次越多,縮進的值就越多,如果將該屬性的值設置爲0,就不會縮進了,這樣可以達到的效果就是可以將擴展和收縮的箭頭隱藏起來,qt內核處理是將該箭頭放到indentation設置的大小區域的,如果設置爲0,就沒有地方放它了,它就會看不見了,達到了隱藏起來的效果,這樣就把QTreeWidget這個bug隱藏起來了,就相當於解決了QTreeWidget的這個bug,既然隱藏了這個擴展和收縮的按鈕,那麼怎麼實現擴展和收縮的功能呢,可以綁定對應的點擊信號和槽函數就可以了。

    connect(ui->treeWidget, &QTreeWidget::itemClicked, [=](QTreeWidgetItem* item,int nidex){

        bool bIsChild = item->data(0, Qt::UserRole).toBool();

        if (!bIsChild)

        {

            item->setExpanded(!item->isExpanded());

        }

    });

類似這樣的代碼就可以達到收縮和隱藏的功能了,既然功能達到了,剩下的就是處理好這個收縮和隱藏的按鈕顯示就可以了,通過自定義item,通過設置如果該item有子節點的話,就畫上去就可以了。

做到了這一步就可以達到基本上大多數treeWidget的效果了,而且通過這種辦法解決了QTreeWidget的這個bug,實現的效果大致就是這樣,還差一點就是縮進了,就是點擊收縮和隱藏按鈕可以達到數據的效果,只是沒有縮進值了,因爲已經設置爲0了,所以不會縮進,通過自定義縮進值,繪製出縮進效果就可以了,如何繪製出來呢,縮進值得大小取決於item的層次大小,首先需要獲取自定義item層次,關鍵代碼如下:

QTreeWidgetItem *MainWindow::addChildNode(QTreeWidgetItem *parent, int index)
{
    QTreeWidgetItem *pDeptItem = new QTreeWidgetItem();
    //設置Data用於區分,Item是分組節點還是子節點,0代表分組節點,1代表子節點
    pDeptItem->setData(0, Qt::UserRole, 1);
    pDeptItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
    pDeptItem->setCheckState(1, Qt::Unchecked);
    int level = 0;
    DepartNodeItem *departNode = dynamic_cast<DepartNodeItem*>(ui->tree->itemWidget(parent, 0));
    if (departNode) {
        level = departNode->getLevel();
        level ++;

}

}

void EmployeeNodeItem::setLevel(int level)
{
    this->m_level = level;
    this->m_indentation = this->m_level * INDENTATION;
    this->m_headLabelWidth = this->m_indentation + HEAD_LABEL_WIDTH;
    ui->lbHeadPic->setMinimumWidth(m_indentation);

}

通過自定義添加節點的接口自定義level實現,這樣itemwidget就能通過自定義實現獲取當前level層次,然後計算出縮進值m_indentation

然後根據這個縮進值繪製出來就可以達到縮進的效果了。

這樣就實現了QTreeWidget的功能同時相當於解決了QTreeWidget這個關於卡頓的bug.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章