Qt的Model/View框架

QT官網(wǎng):Model/View Programming

Qt包含了一系列item view類破花,它們使用model/view架構(gòu)來管理數(shù)據(jù)及其顯示方式的關(guān)系疲吸。模型(model)提供標準接口來存取數(shù)據(jù)摘悴,視圖(view)定義數(shù)據(jù)的顯示方式烦租。即數(shù)據(jù)的存儲和數(shù)據(jù)的顯示是分開的。


Model


View

model/view架構(gòu)

Model-View-Contoller(MVC,模型-視圖-控制器)是一種設(shè)計模式掐松,最初源于Smalltalk,經(jīng)常用來構(gòu)建GUI抡句。在設(shè)計模式中待榔,對MVC的描述如下:

MVC包含3種對象流济。Model是應(yīng)用對象绳瘟,View是屏幕的顯示,Controller定義UI對用戶輸入的響應(yīng)方式斤彼。在MVC之前畅卓,UI管理所有的對象翁潘,而MVC把他們進行了解耦歼争,提供了更大的靈活性沐绒。(數(shù)據(jù)-顯示-控制 進行了分離)

如果view和controller合二為一,就變成了Model/View的架構(gòu)扮超。這仍然把數(shù)據(jù)存儲的方式和數(shù)據(jù)顯示的方式進行了分離出刷,但提供了基于相同原則的更簡單的框架馁龟。這種分離使得在不同的view里顯示相同的數(shù)據(jù)變成可能漆魔,以及當(dāng)實現(xiàn)新的view時不用改變底層的數(shù)據(jù)結(jié)構(gòu)。為了靈活的處理用戶的輸入系瓢,Qt引入了代理(delegate)的概念句灌。

在Qt框架(特別是其模型/視圖編程范式中)涯塔,模型(models)負責(zé)存儲和管理數(shù)據(jù)匕荸,而視圖(views)負責(zé)數(shù)據(jù)的可視化顯示榛搔。代理(delegates)則用于定制視圖中的項目渲染和編輯行為东揣。模型索引是連接這三者的關(guān)鍵嘶卧,它允許視圖和代理以一致的方式引用模型中的數(shù)據(jù),而無需關(guān)心這些數(shù)據(jù)是如何在模型中存儲的侦铜。這種方式使得模型/視圖架構(gòu)非常靈活钉稍,可以處理各種不同類型和結(jié)構(gòu)的數(shù)據(jù)棺耍。


Qt的Model/View架構(gòu)

model和數(shù)據(jù)源進行通信俊卤,為其他組件提供接口害幅。通信的本質(zhì)取決于數(shù)據(jù)源的類型以及模型的實現(xiàn)方式矫限。

view從model中獲取model index,后者提供了對數(shù)據(jù)項的引用取董。通過向model提供model index棍苹,view可以檢索數(shù)據(jù)源中的數(shù)據(jù)項。

在標準視圖中茵汰,代理負責(zé)渲染數(shù)據(jù)項枢里。當(dāng)數(shù)據(jù)項被編輯時,代理會直接使用模型索引(model index)與模型(model)進行通信蹂午。

通常栏豺,如上所述,模型/視圖類可以分為三組:模型(models)豆胸、視圖(views)和代理(delegates)。這些組件中的每一個都由抽象類定義晚胡,這些抽象類提供了公共接口灵奖,并在某些情況下提供了特性的默認實現(xiàn)。抽象類是為了被繼承以提供其他組件所期望的完整功能集估盘;這也允許編寫專門的組件瓷患。

模型、視圖和代理相互之間通過信號和槽進行通信:

模型的信號通知視圖關(guān)于數(shù)據(jù)源中數(shù)據(jù)的更改遣妥。

視圖的信號提供關(guān)于用戶與正在顯示的項目交互的信息擅编。

代理在編輯過程中使用信號來告訴模型和視圖關(guān)于編輯器狀態(tài)的信息。

基類QAbstractItem*:模型-QAbstractItemModel箫踩,視圖-QAbstractItemView沙咏,代理-QAbstractItemDelegate.

模型Models

所有的模型類都基于QAbstractItemModel類。該類定義了可以被視圖和代理使用的班套、訪問數(shù)據(jù)的接口肢藐。數(shù)據(jù)本身不必存儲在模型中,數(shù)據(jù)可以存儲在文件吱韭、數(shù)據(jù)庫或其他組件中吆豹。

QAbstractItemModel提供了訪問數(shù)據(jù)的接口,它為視圖(如表格理盆、列表和樹)展示數(shù)據(jù)提供了足夠的靈活性痘煤。然而,當(dāng)為類似列表和表格的數(shù)據(jù)結(jié)構(gòu)實現(xiàn)新模型時猿规,QAbstractListModel?和?QAbstractTableModel?類是更好的起點衷快,因為它們?yōu)槌R姾瘮?shù)提供了適當(dāng)?shù)哪J實現(xiàn)。這些類中的每一個都可以被子類化姨俩,以提供支持特定類型列表和表格的模型蘸拔。

Qt提供了一些現(xiàn)成的模型师郑,可以用來處理數(shù)據(jù)項:

QStringListModel:用來存儲簡單的QStringList對象。

QStandardItemModel:管理更復(fù)雜的樹形結(jié)構(gòu)的項调窍,每個可以包含任意數(shù)據(jù)宝冕。

QFileSystemModel:提供本地文件系統(tǒng)中關(guān)于文件和路徑的信息。

QSqlQueryModel邓萨,QSqlTableModel地梨,QSqlRelationalTableModel用于訪問數(shù)據(jù)庫。

如果這些標準的模型不能滿足你的需求缔恳,你可以繼承QAbstractItemModel宝剖,QAbstractListModel或QAbstractTableModel來創(chuàng)建自己的模型。

視圖Views

完全實現(xiàn)的類包括:QListView顯示一列項, QTableView用表格顯示數(shù)據(jù)歉甚,QTreeView用層次結(jié)構(gòu)顯示數(shù)據(jù)万细。上述3類都繼承自QAbstractItemView。這些類可以直接使用铃芦,也可以從這些類中派生新的類雅镊。

代理Delegates

QAbstractItemDelegate是所有代理的基類襟雷。默認的實現(xiàn)的類是QStyledItemDelegete刃滓,這是Qt的標準視圖默認使用的類。二者的區(qū)別在于耸弄,QStyledItemDelegate 使用當(dāng)前樣式表進行繪制咧虎。在實現(xiàn)自定義委托時,推薦使用QStyledItemDelegate 作為基類计呈,或者結(jié)合 Qt style sheets砰诵。

排序Sorting

在模型/視圖的架構(gòu)下有2種排序,選擇哪種取決于底層的模型捌显。

如果你的模型是可排序的茁彭,例如它實現(xiàn)了QAbstractItemModel::sort()函數(shù),QTableView和QTreeView提供了API允許你通過編程的方式對模型進行排序扶歪。此外理肺,我們可以使能交互式排序,即運行用戶通過點擊視圖的表頭進行排序善镰,只要把QHeaderView::sortindicatorChanged()信號連接到QTableView::sortByColumn()槽妹萨,和QTreeView::sortByCOlumn()槽。

便捷類

便捷類包括QListWidget炫欺,QTreeWidget和QTableWidget乎完。

這些類沒有Views類靈活,不能和model使用品洛。推薦使用view類來處理數(shù)據(jù)树姨。

如果想利用model/view摩桶,又想使用item-based接口,可以考慮使用view類娃弓,如QListView典格,QTreeView和QTableView,但和QStandartItemModel一起使用台丛。

使用模型和視圖

下面的內(nèi)容解釋如何在qt中使用模型/視圖的模式耍缴。

Qt包含的2中模型

qt提供了2中基本的模型:QStandardItemModel和QFileSystemModel。QStandardItemModel是個多功能的模型挽霉,可用來表示list防嗡,table和tree需要的各種類型的數(shù)據(jù)結(jié)構(gòu)。該模型中保持數(shù)據(jù)項侠坎。

QFileSystemModel用來維護一個目錄中內(nèi)容的信息蚁趁,它不持有任何數(shù)據(jù)項,而是僅僅簡單的展示文件系統(tǒng)中文件夾內(nèi)容实胸。

模型類

基本概念

在模型/視圖架構(gòu)中他嫡,模型為視圖和代理提供了訪問數(shù)據(jù)的標準接口。在Qt中庐完,標準接口定義在QAbstractItemModel類中钢属。不管底層數(shù)據(jù)項的結(jié)構(gòu)如何, QAbstractItemModel的所有子類用層次結(jié)構(gòu)的方式來展現(xiàn)數(shù)據(jù),包括表格门躯。視圖使用它來訪問模型中的數(shù)據(jù)淆党,但和顯示給用戶的信息并不需要嚴格一致。


三種模型

模型通過信號和槽的機制通知所有附屬的視圖讶凉,數(shù)據(jù)改變了染乌。

模型索引 model index

為了保證數(shù)據(jù)的顯示和數(shù)據(jù)的訪問分離,引入了模型索引的概念懂讯。每一片可以通過模型來獲取的信息都被表示成一個模型索引荷憋。視圖和代理通過模型索引來請求被顯示的數(shù)據(jù)。

因此褐望,只有模型需要知道如何獲取數(shù)據(jù)勒庄,且被模型所管理的數(shù)據(jù)類型可以被定義地非常的通用。模型索引中包含一個創(chuàng)建他們的模型的指針譬挚,當(dāng)多個模型同時工作時锅铅,不會導(dǎo)致困擾。

QAbstractItemModel *model = index.model();

模型索引提供了對信息的暫時的引用减宣,還能被用來獲取或修改數(shù)據(jù)盐须,但需要通過模型來實現(xiàn)。由于模型可能隨時重構(gòu)它內(nèi)部的結(jié)構(gòu)漆腌,模型索引可能變得無效贼邓,因此不應(yīng)該被存儲阶冈。如果需要長期引用一條信息,一個persistent model index(持久模型索引)需要被創(chuàng)建塑径。暫時的模型索引用QModelIndex類女坑,而持久的模型索引用QPersitentModelIndex類。

想要獲取數(shù)據(jù)項的模型索引统舀,需要項模型提供3個必要屬性:行號row匆骗,列號column,和父項的模型索引誉简。

行和列

最基本的形式碉就,模型訪問表格,數(shù)據(jù)項用行號和列號來定位闷串。如下所示:

QModelIndex index = model->index(row, column, ...);


模型索引的獲取

數(shù)據(jù)項的父項(parents of items)

對于樹形結(jié)構(gòu)瓮钥,一個項還可能是其他項的父項。因此在獲取模型索引時烹吵,還要提供父項:

QModelIndex index = model->index(row, column, parent);


父項

項的角色(Item Roles)

模型中的數(shù)據(jù)項可以實現(xiàn)不同的角色碉熄,例如Qt::DisplayRule是用來訪問字符串的,在視圖中顯示為text肋拔。標準的角色定義在Qt::ItemDataRole中锈津。視圖用不同的方式展示各種角色的數(shù)據(jù),如下圖所示只损。因此給每個角色提供合適的信息很重要一姿。

QVariant value = model->data(index, role);


數(shù)據(jù)項的角色

最常用的角色都定義在 Qt::ItemDataRole里七咧。通過提供合適的數(shù)據(jù)給每個角色跃惫,模型可以提供暗示(hint)給視圖和代理,告訴他們應(yīng)該如何把數(shù)據(jù)項展示給用戶艾栋。


數(shù)據(jù)的角色

總結(jié):

1.模型索引(Model indexes)為視圖(views)和代理(delegates)提供了關(guān)于模型中項目位置的信息爆存,這種提供信息的方式不依賴于任何底層數(shù)據(jù)結(jié)構(gòu)。

2.數(shù)據(jù)項通過row蝗砾,column以及他們父對象的索引來定位先较。

3.模型索引被模型構(gòu)建,當(dāng)視圖和代理需要的時候悼粮。

4.模型索引有父索引闲勺。

5.如果給一個索引提供了一個invalid的父索引,則表示表示該索引是頂層索引扣猫。

6.角色用來區(qū)分一個item上所包含的不同數(shù)據(jù)菜循。

視圖類

在模型/視圖架構(gòu)中,視圖從模型中獲取數(shù)據(jù)項并展示給用戶看申尤。視圖中展現(xiàn)數(shù)據(jù)的格式可能與數(shù)據(jù)存儲的結(jié)構(gòu)完全不同癌幕,這就是模型/視圖的優(yōu)點衙耕。

視圖通常用來管理數(shù)據(jù)的布局。視圖可以渲染特定的數(shù)據(jù)項勺远,或通過代理來處理渲染和編輯橙喘。

除了展示數(shù)據(jù)外,視圖提供在item中導(dǎo)航胶逢,以及item的選擇厅瞎。

視圖構(gòu)建時可以沒有模型,但想要視圖顯示信息初坠,就必須提供模型磁奖。視圖通過使用selections來跟蹤用戶選擇的items,然后每個視圖維護各自的選擇某筐,或分享給多個視圖比搭。

有些視圖,如QTableView和QTreeView除了顯示items南誊,還顯示header(表頭)身诺,這是通過另一個視圖類實現(xiàn)的,QHeaderView.

使用現(xiàn)成的視圖

Qt提供了3個現(xiàn)成的視圖:QListView, QTreeView和QTableView抄囚。


三種視圖

這三種視圖對絕大多數(shù)應(yīng)用來說是足夠了霉赡。


多個視圖可以共享選擇項,如下所示幔托。

secondTableView->setSelectionModel(firstTableView->selectionModel());


共享選擇項

代理類

不同于MVC的模式穴亏,模型/視圖結(jié)構(gòu)沒有單獨的組件來管理用戶的交互。通常重挑,視圖負責(zé)把模型中的數(shù)據(jù)展示給用戶嗓化,并負責(zé)處理用戶的輸入。為了更靈活的處理用戶的輸入谬哀,交互用代理(delegate)來實現(xiàn)刺覆。代理負責(zé)提供輸入的能力,并且也負責(zé)數(shù)據(jù)項的渲染史煎。代理的標準接口定義在QAbstractItemDelegate類中谦屑。

代理被期望能夠渲染他們的內(nèi)容,通過實現(xiàn)paint()和sizeHint()函數(shù)篇梭。

代理(delegates)中的編輯器可以通過使用控件(widgets)來管理編輯過程氢橙,或者直接處理事件來實現(xiàn)。第一種方法(使用控件)將在本節(jié)的后續(xù)部分中介紹恬偷,并且在“SpinBox Delegate”示例中也有所展示悍手。

Pixelator例子展示了如何創(chuàng)建一個用戶代理來實現(xiàn)對table view的特定渲染。












1.Qt Model/View框架詳解1_qt modelview-CSDN博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市谓苟,隨后出現(xiàn)的幾起案子官脓,更是在濱河造成了極大的恐慌,老刑警劉巖涝焙,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卑笨,死亡現(xiàn)場離奇詭異,居然都是意外死亡仑撞,警方通過查閱死者的電腦和手機赤兴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來隧哮,“玉大人桶良,你說我怎么就攤上這事【谙瑁” “怎么了陨帆?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長采蚀。 經(jīng)常有香客問我疲牵,道長,這世上最難降的妖魔是什么榆鼠? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任纲爸,我火速辦了婚禮,結(jié)果婚禮上妆够,老公的妹妹穿的比我還像新娘识啦。我一直安慰自己,他們只是感情好神妹,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布颓哮。 她就那樣靜靜地躺著,像睡著了一般灾螃。 火紅的嫁衣襯著肌膚如雪题翻。 梳的紋絲不亂的頭發(fā)上揩徊,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天腰鬼,我揣著相機與錄音,去河邊找鬼塑荒。 笑死熄赡,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的齿税。 我是一名探鬼主播彼硫,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拧篮?” 一聲冷哼從身側(cè)響起词渤,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎串绩,沒想到半個月后缺虐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡礁凡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年高氮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片顷牌。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡剪芍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出窟蓝,到底是詐尸還是另有隱情罪裹,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布运挫,位于F島的核電站坊谁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏滑臊。R本人自食惡果不足惜口芍,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望雇卷。 院中可真熱鬧鬓椭,春花似錦、人聲如沸关划。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽贮折。三九已至裤翩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間调榄,已是汗流浹背踊赠。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留每庆,地道東北人筐带。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像缤灵,于是被迫代替她去往敵國和親伦籍。 傳聞我的和親對象是個殘疾皇子蓝晒,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容