QTreeView處理大量資料

2021-07-24 04:01:01 字數 3793 閱讀 7970

如何使qtreeview快速顯示1000萬條資料,並且記憶體佔用量少呢?這個問題困擾我很久,在網上找了好多相關資料,都沒有找到合理的解決方案,今天在這裡把我的解決方案提供給朋友們,供大家相互學習。

我開始使用的qtreewidget 控制項來顯示我的資料,發現該控制項在顯示10000行以下的資料還可以應付的過來,但超過10000條,就明顯感覺到螢幕重新整理就會有卡的現象,而且佔據記憶體很大,雖然操作起來簡單方便,但靈活性沒有qtreeview強大。因為我要顯示的資料量是非常大的,甚至過1000萬,因此,採用qtreewidget來顯示,很顯然不能滿足效能要求,所以打算採用qtreeview來顯示,不羅嗦了,趕快進入正題了,下面講講我是怎麼通過qtreeview來快速顯示1000萬條資料的吧!

1.通過從檔案裡面讀取要顯示的資料,交給qtreeview來顯示,從而不用把資料一次性讀到記憶體,就可以解決記憶體占用大的問題。

2.我們知道資料顯示是通過重新整理來實現的,通過重新整理時,每次只重新整理螢幕可見區域,其他部分不用重新整理的方法,從而解決速度顯示慢的問題。

解決了上面的兩個問題,顯示1億條資料都不會有任何問題,而且顯示速度和記憶體占有量與顯示1000條資料相當,聽起來很誘人啊,下面是我是怎麼通過qtreeview來解決這兩個問題的:

1.過載qabstractitemmodel中的如下函式:  

qvariant headerdata(int section, qt::orientation orientation,

int role = qt::displayrole) const;

qvariant data(const qmodelindex &index, int role) const;

int rowcount(const qmodelindex &parent = qmodelindex()) const;

int columncount(const qmodelindex &parent = qmodelindex()) const;

qmodelindex index(int row, int column,

const qmodelindex &parent = qmodelindex()) const;

qmodelindex parent(const qmodelindex &index) const;

(1)qvariant headerdata(intsection, qt::orientationorientation, int role =qt::displayrole)const;顯示樹視的標題,section表示列,從0開始,orientation表示標題的方向(水平還是垂直),role表式標題欄顯示的方式,當role的角色為qt::displayrole時,表示顯示文字,當然還有其他角色,大家可以參考qt開發手冊。示例**:

qvariant cmymodel::headerdata(int section, qt::orientation orientation, int role) const

return qvariant();

}顯示水平標題,其中pdata是我定義的乙個資料類的物件,在這裡我把該類命名為cdata,headerdata來取出要顯示的資料。

(2)qvariant data(const qmodelindex &index,int role)const;顯示資料,index表示樹節點索引,樹中的每個節點都有乙個對應的該索引,當index = qmodelindex()時,表示該節點是根節點,否則為非根節點。index中存放了該節點在同存節點中的位置資訊(行和列),以及節點的特殊資訊,如index.internalpointer(),這是乙個指標,我們可以通過該指標儲存我們想要的節點資訊,角色同上。示例**:

qvariant cmymodel::data(const qmodelindex &index, int role) const

return qvariant();

}通過getdata來獲取要顯示的資料,該資料方在我們的檔案裡,每次只需要讀取我們想要顯示的資料,不需要把所有的資料都放到記憶體,從而節省了記憶體空間,這樣就解決了上面講的第乙個問題。

(3)int rowcount(const qmodelindex &parent = qmodelindex())const;大家不難猜出該函式是返回該父節點下有多少個子節點,還是來看示例**吧:

int cmymodel::rowcount(const qmodelindex &parent)const

為了簡單起見,這裡不考慮父節點,認為任何節點都存在rowcount()個節點。

(4)int columncount(const qmodelindex &parent = qmodelindex())const;返回父節點有多少列,示例**:

int cmymodel::columncount(const qmodelindex &parent)const

(5)接下來看qmodelindex index(int row, int column, const qmodelindex &parent = qmodelindex()) const;的實現:       

qmodelindex cmchmodel::index(int row, int column, const qmodelindex &parent) const

通過該函式建立節點的索引,我這裡簡單一點,只建立一層節點,若大家要建立多層節點,則要通parent索引裡的資料(如internalpointer())來建立對應的節點,通過createindex的第3個引數來向節點傳入指定的索引資料,由於我這裡不需要建立多層節點,所以我傳入null。那麼我們怎麼建立節點的父子關係呢,聰明的你肯定想到了吧,qmodelindex parent(const qmodelindex &index) const;就是建立父子節點的父子關係的,如果只有一層節點,該函式無須過載,至此我們的顯示資料模型已經實現了,接下來就是要把這個模型通過檢視來表現出來(qtreeview)。

我們看看qtreeview是怎麼來顯示我們上面建立的模型的,看一段簡單的**,大家就明白了:

qtreeview treeview;

cmymodel *pmodel = new cmymodel();

treeview.setmodel(pmodel);

treeview.show();

2.是不是很簡單,到這裡通過qtreeview來處理大量的資料的實現方式差不多講完了,當你按照上面的方式準備處理你的大批量資料時,你就會發現顯示10000行資料還是會卡,這是什麼原因呢?其實這個也困擾我很久,網上也沒有找到相關資料,沒辦法啊,只有啃qtreeview實現的源**,實際上qtreeview確實是顯示可見部分資料(每次顯示1000行資料,按理論上來說1000行足以佔據計算機螢幕,這樣一來不管你資料量是多大,我始終只取1000行資料,所以1億條資料與1000條資料顯示速度是一樣的,只要你一次只讀出要顯示的資料,記憶體占有量也是一樣的),既然問題都解決了,那麼為什麼還會有卡的現象呢?

經過進一步研究qtreeview源**,最後發現耗時的地方是qtreeview第一次重新整理的時候會計算每一行的行高,這樣重新整理時,就要遍歷所有行資料,原來卡是出在這個地方啊,那麼應該怎麼解決呢?實現方法很簡單,就是上面的**多加一行,treeview.setuniformrowheights(true);這樣一來就不會重新整理計算所有行的行高了,至此用qtreeview顯示大批量資料問題得到解決。

最後再補充一下,該實現方式可以適應其他qtableview, qlistview等檢視。

JDBC 批處理 插入大量資料

使用jdbc向資料庫插入100000條記錄,分別使用statement,preparedstatement,及preparedstatement 批處理3種方式進行測試 1 使用statement插入100000條記錄 public void exec connection conn catch s...

大量資料處理問題

1.根據快速排序劃分的思想 1 遞迴對所有資料分成 a,b b b,d 兩個區間,b,d 區間內的數都是大於 a,b 區間內的數 2 對 b,d 重複 1 操作,直到最右邊的區間個數小於100個。注意 a,b 區間不用劃分 3 返回上乙個區間,並返回此區間的數字數目。接著方法仍然是對上一區間的左邊進...

mysql 大量資料處理問題

一 大量資料儲存問題解決方法 分割槽 分表 原則 多利用點記憶體,減輕磁碟io負載,因為io往往是資料庫伺服器的瓶頸 區別 1,實現方式上 mysql的分表是真正的分表,一張表分成很多表後,每乙個小表都是完正的一張表 分割槽不一樣,一張大表進行分割槽後,他還是一張表,不會變成二張表,但是他存放資料的...