通常若是須要對一個視圖進行關鍵字過濾,咱們會使用QT的類QSortFilterProxyModel,將視圖(view)的模型設置爲這個代理類,將代理類的源模型定義爲原始模型,而後定義代理模型的filterKeyColumn, filterRole, filterFixString或filterRegExp等屬性後就能夠實現過濾功能。如:函數
MyTreeModel model; QSortFilterProxyModel sfmodel; MyView view; view.setModel(&sfmodel); sfmodel.setSourceModel(&model); sfmodel.setFilterKeyColumn(0); // optional sfmodel.setFilterRole(Qt::DisplayRole); // default, optional sfmodel.setFilterFixedString("keyword"); sfmodel.setFilterRegExp("[hH]ello");
可是對於TreeView和TreeModel,這樣的作法有些缺陷,若是在子節點上的數據根據過濾規則能夠顯示,但它的parent節點根據過濾規則是不顯示的。這樣一來會由於父節點被過濾掉,而致使符合條件的子節點也一塊兒被過濾掉了。若是須要對這個缺陷進行改進,能夠這樣來作:從QSortFilterProxyModel繼承一個本身的代理類,從新實現它的filterAcceptsRow函數,當節點不是一個葉子節點(在末端,沒有子節點)時不該用過濾規則,只對葉子節點應用過濾規則,這樣就能夠達到上述要求。代碼以下:
spa
bool MyFilterProxyModel::filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const { QModelIndex source_index = sourceModel()->index(source_row, 0, source_parent); if (sourceModel()->rowCount(source_index)>0) return true; else return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); }
上面的代碼會帶來一個新的缺陷,就是對於非葉子節點不該用過濾規則,對於那些沒有子節點符合過濾規則,且自身節點也不符合過濾規則的節點,也會一直在視圖中顯示。若是須要彌補這個問題,能夠繼續作如下的改進:在應用過濾規則時,若是自身不符合過濾規則,再去檢查全部的子節點(遞歸調用至全部的後代節點),若全部的子節點都不符合過濾規則,那麼這個子節點就不顯示,只要有一個後代節點符合規則,就須要顯示這個節點。代碼以下:代理
bool MyFilterProxyModel::filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const { bool filter = QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); if (filter) { return true; } else { // check all decendant's QModelIndex source_index = sourceModel()->index(source_row, 0, source_parent); for (int k=0; k<sourceModel()->rowCount(source_index); k++) { if (filterAcceptsRow(k, source_index)) { return true; } } } return false; }
按照這樣的作法,就能夠達到一個比較理想的過濾效果。code