翻譯|使用教程|編輯:顏馨|2023-05-12 13:53:40.583|閱讀 244 次
概述:本章講述Qt小部件:可編輯樹模型的示例,歡迎查閱~
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
Qt 是目前最先進、最完整的跨平臺C++開發工具。它不僅完全實現了一次編寫,所有平臺無差別運行,更提供了幾乎所有開發過程中需要用到的工具。如今,Qt已被運用于超過70個行業、數千家企業,支持數百萬設備及應用。
The Qt Company是Digia Plc旗下的全資子公司。負責所有Qt活動,包括產品開發,商業和開源授權模式以及在開放管理模式下的Qt工程。其許可、支持和服務能力能夠和開發者緊密合作以確保他們的Qt項目準時部署,不超預算并擁有競爭優勢。
Qt技術交流群:166830288
此示例演示如何實現一個簡單的基于項的樹模型,該模型可與模型/視圖框架的其他類一起使用。
該模型支持可編輯項、自定義標題以及插入和刪除行和列的功能。使用這些功能,還可以插入新的子項,這在支持的示例代碼中顯示。
如模型子類化參考中所述,模型必須為標準模型函數集提供實現:flags()、data()、headerData()、columnCount() 和 rowCount()。此外,分層模型,比如這個,需要提供 index() 和 parent() 的實現。
可編輯模型需要提供 setData() 和 setHeaderData() 的實現,并且必須從其 flags() 函數返回合適的標志組合。
由于這個例子允許改變模型的維度,我們還必須實現insertRows(),insertColumns(),removeRows()和removeColumns()。
與簡單樹模型示例一樣,該模型只是充當類實例集合的包裝器。每個都旨在保存樹視圖中一行項目的數據,因此它包含與每列中顯示的數據對應的值列表。
由于 QTreeView 為模型提供了面向行的視圖,因此很自然地為數據結構選擇面向行的設計,該設計將通過模型向此類視圖提供數據。盡管這使得樹模型不太靈活,并且對于用于更復雜的視圖可能不太有用,但它使設計變得不那么復雜,并且更易于實現。
在設計用于自定義模型的數據結構時,通過 TreeItem::p arent() 等函數公開每個項的父項很有用,因為它將使編寫模型自己的 parent() 函數更容易。類似地,像 TreeItem::child() 這樣的函數在實現模型的 index() 函數時很有幫助。因此,每個都維護有關其父級和子級的信息,使我們能夠遍歷樹結構。該圖顯示了實例如何通過其 parent() 和 child() 函數進行連接。
在所示的示例中,可以通過調用其 child() 函數從根項獲取兩個頂級項 A 和 B,并且這些項中的每一個都從其 parent() 函數返回根節點,盡管這僅針對項 A 顯示。
每個都在其私有成員(QVariant 對象列表)中表示的行中存儲每一列的數據。由于視圖中的每一列和列表中的每個條目之間存在一對一的映射,因此我們提供了一個簡單的 data() 函數來讀取列表中的條目,并提供了一個 setData() 函數來允許修改它們。與項目中的其他函數一樣,這簡化了模型的 data() 和 setData() 函數的實現。
我們將一個項目放在項目樹的根目錄中。此根項對應于空模型索引 QModelIndex(),該索引用于在處理模型索引時表示頂級項的父項。盡管根項在任何標準視圖中都沒有可見的表示形式,但我們使用其內部 QVariant 對象列表來存儲字符串列表,這些字符串將傳遞給視圖以用作水平標題。
在圖中所示的情況下,可以使用標準模型/視圖 API 獲取由 a 表示的信息片段:
QVariant a = model->index(0, 0, QModelIndex()).data();
由于每個項目都包含給定行中每一列的數據片段,因此可以有許多映射到同一對象的模型索引。例如,可以使用以下代碼獲取 b 表示的信息:TreeItem
QVariant b = model->index(1, 0, QModelIndex()).data();
同樣的底層將被訪問以獲得與b.TreeItem相同行的其他模型索引的信息。
在模型類中,當我們在 index() 和 parent() 實現中使用 QAbstractItemModel::createIndex() 創建相應的模型索引時,我們通過為每個項目傳遞一個指針來將對象與模型索引相關聯。我們可以通過在相關模型索引上調用 internalPointer() 函數來檢索以這種方式存儲的指針 - 我們創建自己的 getItem() 函數來為我們完成工作,并從我們的 data() 和 parent() 實現中調用它。
當我們控制項目的創建和銷毀方式時,存儲指向項目的指針很方便,因為我們可以假設從 internalPointer() 獲得的地址是有效的指針。但是,某些模型需要處理從系統中的其他組件獲取的項,并且在許多情況下,無法完全控制項的創建或銷毀方式。在這種情況下,純基于指針的方法需要輔以保護措施,以確保模型不會嘗試訪問已刪除的項目。
幾段數據作為 QVariant 對象存儲在每個實例的成員中。
該圖顯示了由前兩個圖中的標簽 a、b 和 c 表示的信息片段如何存儲在基礎數據結構中的項目 A、B 和 C 中。請注意,模型中同一行的信息片段都是從同一項目獲取的。列表中的每個元素對應于模型中給定行中每列公開的一條信息。
由于該實現是為與 QTreeView 一起使用而設計的,因此我們對其使用實例的方式添加了限制:每個項目必須公開相同數量的數據列。這使得查看模型保持一致,允許我們使用根項來確定任何給定行的列數,并且僅添加創建包含足夠列數數據的項的要求。因此,插入和刪除列是耗時的操作,因為我們需要遍歷整個樹來修改每個項目。
另一種方法是設計類,以便在修改數據項時截斷或擴展單個實例中的數據列表。但是,這種“懶惰”的大小調整方法只允許我們在每行的末尾插入和刪除列,而不允許在每行的任意位置插入或刪除列。
與簡單樹模型示例一樣,需要能夠獲取模型索引,找到相應的 ,并返回與其父項和子項對應的模型索引。
在圖中,我們展示了模型的 parent() 實現如何使用上圖中顯示的項獲取與調用方提供的項的父項對應的模型索引。
指向項 C 的指針是使用 QModelIndex::internalPointer() 函數從相應的模型索引中獲取的。指針在創建時存儲在索引內部。由于子項包含指向其父項的指針,因此我們使用其 parent() 函數來獲取指向項 B 的指針。父模型索引是使用 QAbstractItemModel::createIndex() 函數創建的,將指向項 B 的指針作為內部指針傳遞。
歡迎下載|體驗更多Qt產品
獲取更多信息請咨詢 ;Qt技術交流群:166830288
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn