版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
Ref:/superjoel/article/details/5112120setD^taPBintEvenitcommitDataModelIndex<place”widget|Rowi(CGliumdiel&gat^)ht!p://blog.G5/superjoeliReal'm&at*ofdata(FiEe/Databas^.,JfetchupdatesetD^taPBintEvenitcommitDataModelIndex<place”widget|Rowi(CGliumdiel&gat^)ht!p://blog.G5/superjoeliReal'm&at*ofdata(FiEe/Databas^.,Jfetchupdates&tDatasctDatadata-dataGTiLangeddatarendering|SelectionmodelSelectionmode)Model1McdeEnUser|Painter也色訕i=蒼一般來說,Model里面并沒有真正存儲數(shù)據(jù)(數(shù)據(jù)少的話也可以直接存儲在Model里),它的數(shù)據(jù)是從真正的"肉(raw)"里取得,如一個diskfile,或database的queryresultset等等。那么這個model究竟是干什么用的呢?說白了吧,它就是負責將“肉”數(shù)據(jù)獲取并提供給view,然后將view所做的對“肉”數(shù)據(jù)的修改更新至真正的"肉"中。所以,讀寫文件、操作數(shù)據(jù)庫、網絡通訊等一系列與數(shù)據(jù)打交道的工作就在model中做了。有的時候“肉”可能真的很肥,所以model還有一項重要的工作就是把這些"肉”編號。這樣就出現(xiàn)了ModelIndex這個非常重要的類。一般來說,它使用一個2維的編號(row/colum)來對"肉”編號。但對于tree這種有層次結構的數(shù)據(jù)來說,又加上一個parentindex作為第3個編號。即一個父親下面的葉子也是從0,0開始編號,獲取modelindex的時候用遞歸來實現(xiàn)。0K,現(xiàn)在model已經有了一堆編好號碼的“肉”了,誰來買???“肉”便宜了。。。。。。View適時出現(xiàn),注意,很多view可以同時來買同一塊“肉”。(汗,不開玩笑了,這篇blog快水了)。當view需要顯示某些數(shù)據(jù)時,它們通過modelindex從model中獲取數(shù)據(jù)(調用model的data函數(shù),當model的data變化時,它也會自動發(fā)dataChangedsignal給所有的view以便它們更新)。當然,在view中也可以調用model的setData函數(shù)來設定某個modelindex所對應的數(shù)據(jù)。這里要說明一下model中的數(shù)據(jù),用QVarient來承載,可以是所有Qt支持的類型,比較貼心的是,數(shù)據(jù)可以分成多個角色(role),例如Qt::DisplayRole專用于顯示,Qt::BackgroundRole用于顯示背景色等等。所以在model中,你不光可以對“肉”進行編號,還可以對“肉”進行“深加工”,使它們更“好看”或是更“美味”。View組織這些數(shù)據(jù)并顯示,但卻沒有做真正的顯示工作,真正的工作留給了delegate。Delegate就是MVC中的Coview讓它顯示時它就在paint函數(shù)中顯示。當然,你可以重載這個函數(shù)并實現(xiàn)你自己的顯示。你還可以給一個view設定rowdelegate和columdelegate專用于row和colum。當用戶觸發(fā)了view的edittrigger時(如雙擊鼠標或回車),view開始inplaceedit(beginEditing)。Delegate會在合適的地方創(chuàng)建一個合適的widget(如lineedit或combobox等)處理用戶的輸入,用戶輸入完成以后delegate獲取用戶的輸入并返回。這些輸入可以通過調用model的setData函數(shù)保存到真正的"肉"中。所以Delegate其實就是負責最終顯示數(shù)據(jù)和處理用戶交互的既然由用戶交互,最重要的肯定是用戶的選擇了。說一下selectionmodel。View將用戶選擇的itemindex全部存入selectionmodel中,顯示的時候根據(jù)selectionmodel的內容顯示。另外,多個view可以共享同一個selectionmodel,這樣,當你選中其中的一個時,另一個view中的相應item也會被選中。QtModel/View/main-snapshot/model-view-programming.html介紹Qt4推出了一組新的itemview類,它們使用model/view結構來管理數(shù)據(jù)與表示層的關系。這種結構帶來的功能上的分離給了開發(fā)人員更大的彈性來定制數(shù)據(jù)項的表示,它也提供一個標準的model接口,使得更多的數(shù)據(jù)源可以被這些itemview使用。這里對model/view的結構進行了描述,結構中的每個組件都進行了解釋,給出了一些例子說明了提供的這些類如何使用。Model/View結構Model-View-Controller(MVC),是從Smalltalk發(fā)展而來的一種設計模式,常被用于構建用戶界面。經典設計模式的著作中有這樣的描述:MVC由三種對象組成Model是應用程序對象,ew是它的屏幕表示,Controller定義了用戶界面如何對用戶輸入進行響應°MVC之前,用戶界面設計傾向于三者揉合在一起MVC對它們進行了解耦,提高了靈活性與重用性。假如把view與controller結合在一起,結果就是model/view結構。這個結構依然是把數(shù)據(jù)存儲與數(shù)據(jù)表示進行了分離,它與MVC都基于同樣的思想,但它更簡單一些。這種分離使得在幾個不同的view上顯示同一個數(shù)據(jù)成為可能,也可以重新實現(xiàn)新的view,而不必改變底層的數(shù)據(jù)結構。為了更靈活的對用戶輸入進行處理,引入了delegate這個概念。它的好處是,數(shù)據(jù)項的渲染與編程可以進行定制。如上圖所示,model與數(shù)據(jù)源通訊,并提供接口給結構中的別的組件使用。通訊的性質依賴于數(shù)據(jù)源的種類與model實現(xiàn)的方式。view從model獲取modelindexes,后者是數(shù)據(jù)項的引用。通過把modelindexes提供給model,view可以從數(shù)據(jù)源中獲取數(shù)據(jù)。在標準的views中,delegate會對數(shù)據(jù)項進行渲染,當某個數(shù)據(jù)項被選中時,delegate通過modelindexes與model直接進行交流。總的來說,model/view相關類可以被分成上面所提到的三組:models,views,delegates。這些組件通過抽象類來定義,它們提供了共同的接口,在某些情況下,還提供了缺省的實現(xiàn)。抽象類意味著需要子類化以提供完整的其他組件希望的功能。這也允許實現(xiàn)定制的組件。models,views,delegates之間通過信號,槽機制來進行通訊:從model發(fā)出的信號通知view數(shù)據(jù)源中的數(shù)據(jù)發(fā)生了改變。從view發(fā)出的信號提供了有關被顯示的數(shù)據(jù)項與用戶交互的信息。從delegate發(fā)生的信號被用于在編輯時通知model和view關于當前編輯器的狀態(tài)信息。Models所有的itemmodels都基于QAbstractltemModel類,這個類定義了用于views和delegates訪問數(shù)據(jù)的接口。數(shù)據(jù)本身不必存儲在model,數(shù)據(jù)可被置于一個數(shù)據(jù)結構或另外的類,文件,數(shù)據(jù)庫,或別的程序組件中。關于model的基本概念在ModelClasses部分中描述。QAbstractItemModel提供給數(shù)據(jù)一個接口,它非常靈活,基本滿足views的需要,無論數(shù)據(jù)用以下任何樣的形式表現(xiàn),如tables,lists,trees。然而,當你重新實現(xiàn)一個model時,如果它基于table或list形式的數(shù)據(jù)結構,最好從QAbstractListModel,QAbstractTableModel開始做起,因為它們提供了適當?shù)某R?guī)功能的缺省實現(xiàn)。這些類可以被子類化以支持特殊的定制需求。子類化model的過程在CreateNewModel部分討論QT提供了一些現(xiàn)成的models用于處理數(shù)據(jù)項:QStringListModel用于存儲簡單的QString列表。QStandardltemModel管理復雜的樹型結構數(shù)據(jù)項,每項都可以包含任意數(shù)據(jù)。QDirModel提供本地文件系統(tǒng)中的文件與目錄信息。QSqlQueryModel,QSqlTableModel,QSqlRelationTableModel用來訪問數(shù)據(jù)庫。假如這些標準Model不滿足你的需要,你應該子類化QAbstractItemModel,QAbstractListModel或是QAbstractTableModel來定制。Views不同的view都完整實現(xiàn)了各自的功能QListView把數(shù)據(jù)顯示為一個列表,QTableView把Model中的數(shù)據(jù)以table的形式表現(xiàn),QTreeView用具有層次結構的列表來顯示model中的數(shù)據(jù)。這些類都基于QAbstractltemView抽象基類,盡管這些類都是現(xiàn)成的,完整的進行了實現(xiàn),但它們都可以用于子類化以便滿足定制需求。DelegatesQAbstractItemDelegate是model/view架構中的用于delegate的抽象基類。缺省的delegate實現(xiàn)在QltemDelegate類中提供。它可以用于Qt標準views的缺省delegate.排序在model/view架構中,有兩種方法進行排序,選擇哪種方法依賴于你的底層Model。假如你的model是可排序的,也就是它重新實現(xiàn)了QAbstractltemModel::sort()函數(shù)QTableView與QTreeView都提供了API,允許你以編程的方式對Model數(shù)據(jù)進行排序。另外,你也可以進行交互方式下的排序(例如,允許用戶通過點擊view表頭的方式對數(shù)據(jù)進行排序),可以這樣做:把QHeaderView::sectionClicked()信號與QTableView::sortByColum()槽或QTreeView::sortByColumn()槽進行聯(lián)結就好了。另一種方法是,假如你的model沒有提供需要的接口或是你想用listview表示數(shù)據(jù),可以用一個代理model在用view表示數(shù)據(jù)之前對你的model數(shù)據(jù)結構進行轉換。便利類許多便利類都源于標準的view類,它們方便了那些使用Qt中基于項的view與table類,它們不應該被子類化,它們只是為Qt3的等價類提供一個熟悉的接口。這些類有QListWidget,QTreeWidget,QTableWidget,它們提供了如Qt3中的QListBox,QlistView,QTable相似的行為。這些類比View類缺少靈活性,不能用于任意的models,推介使用model/view的方法處理數(shù)據(jù)。介紹Qt提供了兩個標準的models:QStandardltemModel和QDirModelQStandardltemModel是一個多用途的model,可用于表示list,table,treeviews所需要的各種不同的數(shù)據(jù)結構。這個model也持有數(shù)據(jù)。QDirModel維護相關的目錄內容的信息,它本身不持有數(shù)據(jù),僅是對本地文件系統(tǒng)中的文件與目錄的描述。QDirModel是一個現(xiàn)成的model,很容易進行配置以用于現(xiàn)存的數(shù)據(jù),使用這個model,可以很好地展示如何給一個現(xiàn)成的view設定model,研究如何用modelindexes來操縱數(shù)據(jù)。model與views的搭配使用QListView與QTreeView很適合與QDirModel搭配。下面的例子在treeview與listview顯示了相同的信息QDirModel提供了目錄內容數(shù)據(jù)。這兩個Views共享用戶選擇,因此每個被選擇的項在每個view中都會被咼亮。■同xTwoviewsontothesamedirectorymodel■■N^me沁|Type|Modified_extensions上J3280Direclary2004-04-19T12:...』FAQ2080Dir&ct&ry2004-04-19T12:...Qjinclude由臥佬nsion5104Directory2OOW19T12;,.,fllNSTALLrOFAQ7777FAQFile2OO4-O4-13T12...□lib申“_indude10640Dirertary2OD4-O4-19T12:..._JLICENSE.GPLhDINSTALL4482INSTALLFile2OO4-O4-19T12..._JLICENSE.QPL白“_』ib72DirEdory2004-04-19T12:,.,_JMakefile:由」72Directory2004-04-19T12:...□MANIFEST744Dirprtory2004-04-19T12:..._nnksp-ecs=:■JREADME63READMEFile2004-04-19T12:,.,_||3iC5hJLICENSE.GPL18361GPLFile2OD4-O4-19T12:...」PLATFORMS”二|LI匚ENSE.QPL4689QPLFile2OD4-O4-19T12:..._pluginsL-[1Makefile2751File2OO3-O8-11T1G:...^1_qrnalce屮|111JREADMEzl先裝配出一個QDirModel以供使用,再創(chuàng)建views去顯示目錄的內容。這給我展示了使用model的最簡單的方式。model的創(chuàng)建與使用都在main()函數(shù)中完成:intmain(intargc,char*argv[]){QApplicationapp(argc,argv);QSplitter*splitter=newQSplitter;QDirModel*model=newQDirModel;〃從缺省目錄創(chuàng)建數(shù)據(jù)QTreeView*tree=newQTreeView(splitter);tree->setModel(model);tree->setRootlndex(model->index(QDir::currentPath()));QListView*list=newQListView(splitter);list->setModel(model);list->setRootlndex(model->index(QDir::currentPath()));〃配置一個view去顯示model中的數(shù)據(jù),只需要簡單地調用setModel(),并把目錄model作為參數(shù)傳遞〃setRootlndex()告訴views顯示哪個目錄的信息,這需要提供一個modelindex,然后用這個//modelindex去model中去獲取數(shù)據(jù)//index()這個函數(shù)是QDirModel特有的,通過把一個目錄做為參數(shù),得到了需要的modelindex//其他的代碼只是窗口show出來,進入程序的事件循環(huán)就好了splitter->setWindowTitle("Twoviewsontothesamedirectorymodel");splitter->show();returnapp.exec();}上面的例子并沒有展示如何處理數(shù)據(jù)項的選擇,這包括很多細節(jié),以后會提到。Model類基本概念在model/view構架中,model為view和delegates使用數(shù)據(jù)提供了標準接口。在Qt中,標準接口QAbstractltemModel類中被定義。不管數(shù)據(jù)在底層以何種數(shù)據(jù)結構存儲,QAabstractltemModel的子類會以層次結構的形式來表示數(shù)據(jù),結構中包含了數(shù)據(jù)項表。我們按這種約定來訪問model中的數(shù)據(jù)項,但這個約定不會對如何顯示這些數(shù)據(jù)有任何限制。數(shù)據(jù)發(fā)生改變時,model通過信號槽機制來通知關聯(lián)的views0LisftModelTabkM-oddTreeModel1Root加ncQcmnwWcokjmn卜1cocpn;01HootitefnModelIndexes為了使數(shù)據(jù)存儲與數(shù)據(jù)訪問分開,引入了modelindex的概念。通過modelindex,可以引用model中的數(shù)據(jù)項,Views和delegates都使用indexes來訪問數(shù)據(jù)項,然后再顯示出來。因此,只有model需要了解如何獲取數(shù)據(jù),被model管理的數(shù)據(jù)類型可以非常廣泛地被定義。Modelindexes包含一個指向創(chuàng)建它們的model的指針,這會在配合多個model工作時避免混亂。QAbstractltemModel*model=index.model();modelindexes提供了對一項數(shù)據(jù)信息的臨時引用,通過它可以訪問或是修改model中的數(shù)據(jù)。既然model有時會重新組織內部的數(shù)據(jù)結構,這時modelindexes便會失效,因此不應該保存臨時的modelindexes。假如需要一個對數(shù)據(jù)信息的長期的引用,那么應該創(chuàng)建一個persistentmodelindex。這個引用會保持更新。臨時的modelindexes由QModelIndex提供,而具有持久能力的modelindexes則由QPersistentModelIndex提供。在獲取對應一個數(shù)據(jù)項的modelindex時,需要考慮有關于model的三個屬性:行數(shù),列數(shù),父項的modelindex。行與列在最基本的形式中,一個model可作為一個簡單的表來訪問,每個數(shù)據(jù)項由行,列數(shù)來定位。這必不意味著底層的數(shù)據(jù)用數(shù)組結構來存儲。行和列的使用僅僅是一種約定,它允許組件之間相互通訊。可以通過指定model中的行列數(shù)來獲取任一項數(shù)據(jù),可以得到與數(shù)據(jù)項一一對應的那個index。QModelIndexindex=model->index(row,column,...);Model為簡單的,單級的數(shù)據(jù)結構如list與tables提供了接口,它們如上面代碼所顯示的那樣,不再需要別的信息被提供。當我們在獲取一個
modelindex時,我們需要提供另外的信息。T^bleModelABCHootiterrtrowABCHootiterrtrow-0row=1row-2row-3上圖代表一個基本的tablemodel,它的每一項用一對行列數(shù)來定位。通過行列數(shù),可以獲取代表一個數(shù)據(jù)項的modelindex.QModellndexindexA=model->index(0,0,QModellndex());QModellndexindexB=model->index(1,1,QModelIndex());QModellndexindexC=model->index(2,1,QModelIndex());一個model的頂級項,由QModelIndex()取得,它們上式被用作父項。父項類似于表的接口在搭配使用table或listview時理想的,這種行列系統(tǒng)與view顯示的方式是確切匹配的。然則,像treeviews這種結構需要model提供更為靈活的接口來訪問數(shù)據(jù)項。每個數(shù)據(jù)項可能是別的項的父項,上級的項可以獲取下級項的列表。當獲取model中數(shù)據(jù)項的index時,我們必須指定關于數(shù)據(jù)項的父項的信息。在model外部,引用一個數(shù)據(jù)項的唯一方法就是通過modelindex,因此需要在求取modelindex時指定父項的信息。QModellndexindex=model->index(row,column,parent);上圖中,A項和C項作為model中頂層的兄弟項:QModelIndexindexA=model->index(0,0,QModellndex());QModelIndexindexC=model->index(2,1,QModelIndex());A有許多孩子,它的一個孩子B用以下代碼獲?。篞ModelIndexindexB=model->index(1,0,indexA);項角色model中的項可以作為各種角色來使用,這允許為不同的環(huán)境提供不同的數(shù)據(jù)。舉例來說,Qt::DisplayRole被用于訪問一個字符串,它作為文本會在view中顯示。典型地,每個數(shù)據(jù)項都可以為許多不同的角色提供數(shù)據(jù),標準的角色在Qt::ItemDataRole中定義。我們可以通過指定modelindex與角色來獲取我們需要的數(shù)據(jù):QVariantvalue=model->data(index,role);角色指出了從model中引用哪種類型的數(shù)據(jù)。views可以用不同的形式顯示角色,因此為每個角色提供正確的信息是非常重要的。通過為每個角色提供適當數(shù)據(jù),model也為views和delegates提供了暗示,如何正確地把這些數(shù)據(jù)項顯給用戶。不同的views可以自由地解析或忽略這些數(shù)據(jù)信息,對于特殊的場合,也可以定義一些附加的角色。概念總結:1,Modelindexes為views與delegages提供model中數(shù)據(jù)項定位的信息,它與底層的數(shù)據(jù)結構無關。通過指定行,列數(shù),父項的modelindex來引用數(shù)據(jù)項。依照別的組件的要求,modelindexes被model構建。使用index()時,如果指定了有效的父項的modelindex,那么返回得到的modelindex對應于父項的某個孩子。使用index()時,如果指定了無效的父項的modelindex,那么返回得到的modelindex對應于頂層項的某個孩子。6,角色對一個數(shù)據(jù)項包含的不同類型的數(shù)據(jù)給出了區(qū)分。使用ModelIndexesQDirModel*model=newQDirModel;QModellndexparentindex=model->index(QDir::currentPath());intnumRows=model->rowCount(parentlndex);for(introw=0;row<numRows;++row){QModelIndexindex=model->index(row,0,parentIndex);tringtext=model->data(index,Qt::DisplayRole).toString();//Displaythetextinawidget.}以上的例子說明了從model中獲取數(shù)據(jù)的基本原則:1,model的尺寸可以從rowCount()與columnCount()中得出。這些函數(shù)通常都需要一個表示父項的modelindex。2,modelindexes用來從model中訪問數(shù)據(jù)項,數(shù)據(jù)項用行,列,父項modelindex定位。為了訪問model頂層項,可以使用QModelIndex()指定。數(shù)據(jù)項為不同的角色提供不同的數(shù)據(jù)。為了獲取數(shù)據(jù),除了modelindex之外,還要指定角色。創(chuàng)建新的Models介紹model/view組件之間功能的分離,允許創(chuàng)建model利用現(xiàn)成的views。這也可以使用標準的功能圖形用戶接口組件像QListView,QTableView和QTreeView來顯示來自各種數(shù)據(jù)源的數(shù)據(jù)為。QAbstractListModel類提供了非常靈活的接口,允許數(shù)據(jù)源以層次結構的形式來管理信息,也允許以某種方式對數(shù)據(jù)進行插入、刪除、修改和存儲。它也提供了對拖拽操作的支持。QAbstractListModel與QAbstractTableModel為簡單的非層次結構的數(shù)據(jù)提供了接口,對于比較簡單的list和tablemodels來說,這是不錯的一個開始點。設計一個Model當我們?yōu)榇嬖诘臄?shù)據(jù)結構新建一個model時,首先要考慮的問題是應該選用哪種model來為這些數(shù)據(jù)提供接口。假如數(shù)據(jù)結構可以用數(shù)據(jù)項的列表或表來表示,那么可以考慮子類化QAbstractListModel或QAbstractTableModel,既然這些類已經合理地對許多功能提供缺省實現(xiàn)。然而,假如底層的數(shù)據(jù)結構只能表示成具有層次結構的樹型結構,那么必須得子類化QAbstractItemModel無論底層的數(shù)據(jù)結構采取何種形式,在特定的model中實現(xiàn)標準的QAbstractItemModelAPI總是一個不錯的主意,這使得可以使用更自然的方式對底層的數(shù)據(jù)結構進行訪問。這也使得用數(shù)據(jù)構建model更為容易,其他的model/view組件也可以使用標準的API與之進行交互。一個只讀model示例這個示例實現(xiàn)了一個簡單的,非層次結構的,只讀的數(shù)據(jù)model,它基于QStringistModel類。它有一個QStringList作為它內部的數(shù)據(jù)源,只實現(xiàn)了一些必要的接口。為了簡單化,它子類化了QAbstractListModel,這個基類提供了合理的缺省行為,對外提供了比QAbstractItemModel更為簡單的接口。當我們實現(xiàn)一個model時,不要忘了QAbstractItemModel本身不存儲任何數(shù)據(jù),它僅僅提供了給views訪問數(shù)據(jù)的接口。classStringListModel:publicQAbstractListModel{Q_OBJECTpublic:StringListModel(constQStringList&strings,QObject*parent=0):QAbstractListModel(parent),stringList(strings){}introwCount(constQModelIndex&parent=QModellndex())const;QVariantdata(constQModelIndex&index,introle)const;QVariantheaderData(intsection,Qt::Orientationorientation,introle=Qt::DisplayRole)const;private:QStringListstringList;};除了構造函數(shù),我們僅需要實現(xiàn)兩個函數(shù):rowCount()返回model中的行數(shù),data()返回與特定modelindex對應的數(shù)據(jù)項。具有良好行為的model也會實現(xiàn)headerData(),它返回tree和tableviews需要的,在標題中顯示的數(shù)據(jù)。因為這是一個非層次結構的model,我們不必考慮父子關系。假如model具有層次結構,我們也應該實現(xiàn)index()與parent()函數(shù)。Model的尺寸我們認為model中的行數(shù)與stringlist中的string數(shù)目一致:intStringListModel::rowCount(constQModellndex&parent)const{returnstringList.count();}在缺省情況下,從QAbstractListModel派生的model只具有一列,因此不需要實現(xiàn)columnCount()。Model標題與數(shù)據(jù)QVariantStringListModel::data(constQModelIndex&index,introle)const{if(!index.isValid())returnQVariant();if(index.row()>=stringList.size())returnQVariant();if(role==Qt::DisplayRole)returnstringList.at(index.row());elsereturnQVariant();}QVariantStringListModel::headerData(intsection,Qt::Orientationorientation,introle)const{if(role!=Qt::DisplayRole)returnQVariant();if(orientation==Qt::Horizontal)returnQString("Column%1").arg(section);elsereturnQString("Row%1").arg(section);}一個數(shù)據(jù)項可能有多個角色,根據(jù)角色的不同輸出不同的數(shù)據(jù)。上例中,model中的數(shù)據(jù)項只有一個角色,DisplayRole,然而我們也可以重用提供給DisplayRole的數(shù)據(jù),作為別的角色使用,如我們可以作為ToolTipRole來用??删庉嫷膍odel上面我們演示了一個只讀的model,它只用于向用戶顯示,對于許多程序來說,可編輯的listmodel可能更有用。我們只需要給只讀的model提供另外兩個函數(shù)flags()與setData()的實現(xiàn)。下列函數(shù)聲明被添加到類定義中:Qt::ltemFlagsflags(constQModelIndex&index)const;boolsetData(constQModelIndex&index,constQVariant&value,introle=Qt::EditRole);讓model可編輯delegate會在創(chuàng)建編輯器之前檢查數(shù)據(jù)項是否是可編輯的。model必須得讓delegate知道它的數(shù)據(jù)項是可編輯的。這可以通過為每一個數(shù)據(jù)項返回一個正確的標記得到,在本例中,我們假設所有的數(shù)據(jù)項都是可編輯可選擇的:Qt::ItemFlagsStringListModel::flags(constQModelIndex&ndex)const{if(!index.isValid())returnQt::ltemlsEnabled;returnQAbstractltemModel::flags(index)|Qt::ItemIsEditable;}我們不必知道delegate執(zhí)行怎樣實際的編輯處理過程,我們只需提供給delegate一個方法,delegate會使用它對model中的數(shù)據(jù)進行設置。這個特殊的函數(shù)就是setData():boolStringListModel::setData(constQModelIndex&ndex,constQVariant&value,introle){if(index.isValid()&&role==Qt::EditRole){stringList.replace(index.row(),value.toString());emitdataChanged(index,index);returntrue;}returnfalse;}當數(shù)據(jù)被設置后,model必須得讓views知道一些數(shù)據(jù)發(fā)生了變化,這可通過發(fā)射一個dataChanged()信號實現(xiàn)。因為只有一個數(shù)據(jù)項發(fā)生了變化,因此在信號中說明的變化范圍只限于一個modelindex。插入,刪除行在model中改變行數(shù)與列數(shù)是可能的。當然在本列中,只考慮行的情況,我們只需要重新實現(xiàn)插入、刪除的函數(shù)就可以了,下面應在類定義中聲明:boolinsertRows(intposition,introws,constQModelIndex&index=QModelIndex());boolremoveRows(intposition,introws,constQModelIndex&index=QModelIndex());既然model中的每行對應于列表中的一個string,因此,insertRows()函數(shù)在stringlist中指定位置插入一個空string,父index通常用于決定model中行列的位置,本例中只有一個單獨的頂級項,困此只需要在list中插入空string0boolStringListModel::insertRows(intposition,introws,constQModellndex&parent){beginlnsertRows(QModellndex(),position,position+rows-1);for(introw=0;row<rows;++row){stringList.insert(position,"");}endInsertRows();returntrue;}beginInsertRows()通知其他組件行數(shù)將會改變。endInsertRows()對操作進行確認與通知。返回true表示成功。刪除操作與插入操作類似:boolStringListModel::removeRows(intposition,introws,constQModelIndex&parent){beginRemoveRows(QModellndex(),position,position+rows-1);for(introw=0;row<rows;++row){stringList.removeAt(position);}endRemoveRows();returntrue;}View類概念在model/view架構中,view從model中獲得數(shù)據(jù)項然后顯示給用戶。數(shù)據(jù)顯示的方式不必與model提供的表示方式相同,可以與底層存儲數(shù)據(jù)項的數(shù)據(jù)結構完全不同。內容與顯式的分離是通過由QAbstractltemModel提供的標準模型接口,由QAsbstractltemview提供的標準視圖接口共同實現(xiàn)的。普遍使用modelindex來表示數(shù)據(jù)項0view負責管理從model中讀取的數(shù)據(jù)的外觀布局。它們自己可以去渲染每個數(shù)據(jù)項,也可以利用delegate來既處理渲染又進行編輯。除了顯示數(shù)據(jù),views也處理數(shù)據(jù)項的導航,參與有關于數(shù)據(jù)項選擇的部分功能。view也實現(xiàn)一些基本的用戶接口特性,如上下文菜單與拖拽功能。view也為數(shù)據(jù)項提供了缺省的編程功能,也可搭配delegate實現(xiàn)更為特殊的定制編輯的需求。一個view創(chuàng)建時必不需要model,但在它能顯示一些真正有用的信息之前,必須提供一個model。view通過使用selections來跟蹤用戶選擇的數(shù)據(jù)項。每個view可以維護單獨使用的selections,也可以在多個views之間共享。有些views,如QTableView和QTreeView,除數(shù)據(jù)項之外也可顯示標題(Headers),標題部分通過一個view來實現(xiàn),QHeaderView。標題與view—樣總是從相同的model
中獲取數(shù)據(jù)。從modeI中獲取數(shù)據(jù)的函數(shù)是QabstractltemModel::headerDate(),—般總是以表單的形式中顯示標題信息??梢詮腝HeaderView子類化,以實現(xiàn)更為復雜的定制化需求。使用現(xiàn)成的viewQt提供了三個現(xiàn)成的view類,它們能夠以用戶熟悉的方式顯示model中的數(shù)據(jù)。QListView把model中的數(shù)據(jù)項以一個簡單的列表的形式顯示,或是以經典的圖標視圖的形式顯示。QTreeView把model中的數(shù)據(jù)項作為具有層次結構的列表的形式顯示,它允許以緊湊的深度嵌套的結構進行顯示。QTableView卻是把model中的數(shù)據(jù)項以表格的形式展現(xiàn),更像是一個電子表格應用程序的外觀布局。ii1”曲,ii1”曲,JnewJffiw.pra斶[締除IbjDhAiyQJ.0聆曲腎M嬸,1JvwvltwAb41(-I—1J以上這些標準view的行為足以應付大多數(shù)的應用程序,它們也提供了一些基本的編輯功能,也可以定制特殊的需求。使用model以前的例子中創(chuàng)建過一個stringlistmodel,可以給它設置一些數(shù)據(jù),再創(chuàng)建一個view把model中的內容展示出來:intmain(intargc,char*argv[]){QApplicationapp(argc,argv);//Unindentedforquotingpurposes:QStringListnumbers;numbers<<"One"<<"Two"<<"Three"<<"Four"<<"Five";QAbstractltemModel*model=newStringListModel(numbers);〃要注意的是,這里把StringListModel作為一個QAbstractItemModel來使用。這樣我們就可以〃使用model中的抽象接口,而且如果將來我們用別的model代替了當前這個model,這些代碼也會照樣工作。//QListView提供的列表視圖足以滿足當前這個model的需要了。QListView*view=newQListView;view->setModel(model);view->show();returnapp.exec();}view會渲染model中的內容,通過model的接口來訪問它的數(shù)據(jù)。當用戶試圖編輯數(shù)據(jù)項時,view會使用缺省的delegate來提供一個編輯構件。一個model,多個views為多個views提供相同的model是非常簡單的事情,只要為每個view
設置相同的model。QTableView*firstTableView=newQTableView;QTableView*secondTableView=newQTableView;firstTableView->setModel(model);secondTableView->setModel(model);在model/view架構中信號、槽機制的使用意味著model中發(fā)生的改變會傳遞中聯(lián)結的所有view中,這保證了不管我們使用哪個view,不管我們使用哪個view,訪問的都是同樣的一份數(shù)據(jù)。上面的圖展示了一個model上的兩個不同的views,盡管在不同的view中顯示的model中的數(shù)據(jù)是一致的,每個view都維護它們自己的內部選擇模型,但有時候在某些情況下,共享一個選擇模型也是合理的。處理數(shù)據(jù)項的選擇view中數(shù)據(jù)項選擇機制由QltemSelectionModel類提供。所有標準的view缺省都構建它們自己的選擇模型,以標準的方式與它們交互。選擇模型可以用selectionModel()函數(shù)取得,替代的選擇模型也可以通過setSelectionModel()來設置。當我們想在一個model上提供多個一致的views時,這種對選擇模型的控制能力非常有用。通常來講,除非你子類化一個model或view,你不必直接操縱selections的內容。多個views之間共享選擇接著上邊的例子,我們可以這樣:secondTableView->setSelectionModel(firstTableView->selectionModel());現(xiàn)在所有views都在同樣的選擇模型上操作,數(shù)據(jù)與選擇項都保持同步。上面的例子中,兩個view的類型是相同的,假如這兩個view類型不同,那么所選擇的數(shù)據(jù)項在每個view中的表現(xiàn)形式會有很大的不同。例如,在一個tableview中一個連續(xù)的選擇,在一個treeview中表現(xiàn)出來的可能會是幾個高亮的數(shù)據(jù)項片斷的組合。在views中選擇數(shù)據(jù)項概念用于新的view類中的選擇模型比Qt3中的模型有了很大的改進。它為基于model/view架構的選擇提供了更為全面的描述。盡管對提供了的views來說,負責操縱選擇的標準類已經足以應付,但是你也可以創(chuàng)建特定的選擇模型來滿足你特殊的需求。關于在view被選擇的數(shù)據(jù)項的信息保持在QltemSelectionModel類的實例中。它也為每個獨立的model中的數(shù)據(jù)項維護modelindexes信息,與任何views都關聯(lián)關系。既然一個model可用于多個views,那么在多個views之間共享選擇信息也是可以做到的,這使得多個views可以以一致的方式進行顯示。選擇由多個選擇范圍組成。通過僅僅記錄開始modelindexes與結束modelindexes,最大化地記錄了可以選擇的范圍。非連續(xù)選擇數(shù)據(jù)項由多個選擇范圍來描述。選擇模型記錄modelindexes的集合來描述一個選擇。最近選擇的數(shù)據(jù)項被稱為currentselection。應用程序可以通過使用某種類型的選擇命令來修改選擇的效果。在進行選擇操作時,可以把QItemSelectionModel看成是model中所有數(shù)據(jù)項選擇狀態(tài)的一個記錄。一旦建立一個選擇模型,所有項的集合都可以選擇,撤消選擇,或者選擇狀態(tài)進行切換而不需要知道哪個數(shù)據(jù)項是否已經被選擇過。所有被選擇的項的indexes在任何時候都可以得到,通過信號槽機制可以通知別的組件發(fā)生的變化。使用選擇模型標準view類提供了缺省的選擇模型,它們可以在大次數(shù)程序中使用。一個view中的選擇模型可以通過調用view的函數(shù)selectionModel()取得,也可以通過setSelectionModel()在多個views之間共享選擇模型,因此總的來說構建一個新的模型一般情況不太必要。通過給QltemSelection指定一個model,—對modelindexes,可以創(chuàng)建一個選擇。indexes的用法依賴于給定的model,這兩個indexes被解釋成選擇的區(qū)塊中的左上角項和右下角項。model中的項的選擇服從于選擇模型。選擇項構建一個tablemodel,它有32個項,用一個tableview進行顯示:TableModel*model=newTableModel(8,4,&app);QTableView*table=newQTableView(O);table->setModel(model);QItemSelectionModel*selectionModel=table->selectionModel();QModelIndextopLeft;QModelIndexbottomRight;topLeft=model->index(0,0,QModelIndex());bottomRight=model->index(5,2,QModelIndex());QItemSelectionselection(topLeft,bottomRight);selectionModel->select(selection,QltemSelectionModel::Select);結果如下:讀取選擇狀態(tài)存儲在選擇模型中indexes可以用selectionlndexes()函數(shù)來讀取。它返回一個未排序的modelindexes列表,我們可以遍歷它,如果我們知道他們關聯(lián)于哪個model的話。QModellndexListindexes=selectionModel->selectedlndexes();QModellndexindex;foreach(index,indexes){QStringtext=QString(”(%1,%2)").arg(index.row()).arg(index.column());model->setData(index,text);}選擇模型在選擇發(fā)生變化時會發(fā)出信號。這用于通知別的組件包括整體與當前焦點項所發(fā)生的變化。我們可以連接selectionChanged()信號到一個槽,檢查當信號產生時哪些項被選擇或被取消選擇。這個槽被調用時帶有兩個參數(shù),它們都是QItemSelection對象,一個包含新被選擇的項,另一個包含新近被取消選擇的項。下面的代碼演示了給新選擇的項添加數(shù)據(jù)內容,新近被取消選擇的項的內容被清空。voidMainWindow::updateSelection(constQItemSelection&selected,constQItemSelection&deselected){QModellndexindex;QModellndexListitems=selected.indexes();foreach(index,items){QStringtext=QString(”(%1,%2)").arg(index.row()).arg(index.column());model->setData(index,text);}items=deselected.indexes();foreach(index,items)model->setData(index,"");}也可以通過響應currentChanged()信號來跟蹤當前焦點項.對應的槽就有兩個接收參數(shù),一個表示之前的焦點,另一個表示當前的焦點。voidMainWindow::changeCurrent(constQModelIndex¤t,constQModelIndex&previous){statusBar()->showMessage(tr("Movedfrom(%1,%2)to(%3,%4)").arg(previous.row()).arg(previous.column()).arg(current.row()).arg(current.column()));}更新選擇選擇指令是通過選擇標志提供的,它被定義在QItemSelectionModel::SelectionFlag中。常用的有Select標記,Toggle標記,Deselect標記‘Current標記,Clear標記,其意義一目了然。沿上面例子的結果執(zhí)行以下代碼:QltemSelectiontoggleSelection;topLeft=model->index(2,1,QModelIndex());bottomRight=model->index(7,3,QModelIndex());toggleSelection.select(topLeft,bottomRight);selectionModel->select(toggleSelection,QltemSelectionModel::Toggle);結果如下:缺省情況下,選擇指令只針對單個項(由modelindexes指定)。然而,選擇指令可以通過與另外標記的結合來改變整行和整列。舉例來說,假如你只使用一個index來調用select(),但是用Select標記與Rows標記的組合,那么包括那個項的整行都將被選擇。看以下示例:QItemSelectioncolumnSelection;topLeft=model->index(0,1,QModelIndex());bottomRight=model->index(0,2,QModelIndex());columnSelection.select(topLeft,bottomRight);selectionModel->select(columnSelection,QItemSelectionModel::Select|QltemSelectionModel::Columns);QItemSelectionrowSelection;topLeft=model->index(0,0,QModelIndex());bottomRight=model->index(1,0,QModelIndex());rowSelection.select(topLeft,bottomRight);selectionModel->select(rowSelection,QItemSelectionModel::Select|QItemSelectionModel::Rows);結果如下選擇模型中所有項為了選擇model中的所有項,必須先得創(chuàng)建一個選擇,它包括當前層次上的所有項:QModellndextopLeft=model->index(0,0,parent);QModellndexbottomRight=model->index(model->rowCount(parent)-1,model->columnCount(parent)-1,parent);QItemSelectionselection(topLeft,bottomRight);selectionModel->select(selection,QltemSelectionModel::Select);頂級index可以這樣:QModelIndexparent=QModelIndex();對具有層次結構的model來說,可以使用hasChildren()函數(shù)來決定給定項是否是其它項的父項。Delegate類概念與MVC模式不同,model/view結構沒有用于與用戶交互的完全獨立的組件。一般來講,view負責把數(shù)據(jù)展示給用戶,也處理用戶的輸入。為了獲得更多的靈性性,交互通過delegagte執(zhí)行。它既提供輸入功能又負責渲染view中的每個數(shù)據(jù)項??刂芼elegates的標準接口在QAbstractltemDelegate類中定義。Delegates通過實現(xiàn)paint()和sizeHint()以達到渲染內容的目的。然而,簡單的基于widget的delegates,可以從QItemDelegate子類化,而不是QAbstractltemDelegate,這樣可以使用它提供的上述函數(shù)的缺省實現(xiàn)。delegate可以使用widget來處理編輯過程,也可以直接對事件進行處理。使用現(xiàn)成的delegateQt提供的標準views都使用QItemDelegate的實例來提供編輯功能。它以普通的風格來為每個標準view渲染數(shù)據(jù)項。這些標準的views包括:QListView,QTableView,QTreeView。所有標準的角色都通過標準views包含的缺省delegate進行處理。一個view使用的delegate可以用itemDelegate()函數(shù)取得,而setItemDelegate()函數(shù)可以安裝一個定制delegateo一個簡單的delegate這個delegate使用QSpinBox來提供編輯功能。它主要想用于顯示整數(shù)的models上。盡管我們已經建立了一個基于整數(shù)的tablemodel,但我們也可以使用QStandardltemModel,因為delegate可以控制數(shù)據(jù)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年度××企業(yè)vi設計合同
- 2024年度XX影視作品制作合同
- 2024烏魯木齊市國有土地上房屋征收補償合同
- 2024年度智能工廠設計與建設合同
- 公司員工試用期轉正個人工作總結
- 會計專業(yè)頂實習報告錦集五篇
- 中秋節(jié)晚會精彩致辭范文(6篇)
- 2024年二手房買賣合同模板(含裝修情況)
- 2024年度健身服務承包經營合同協(xié)議書
- 2024年度知識產權許可使用合同:含許可范圍、許可費用、使用期限
- 醫(yī)學創(chuàng)新與科學研究知到章節(jié)答案智慧樹2023年岳陽職業(yè)技術學院
- 社會體育導論教學教案
- 廠房物業(yè)管理服務合同
- 心理健康家長會(課件)-小學生主題班會通用版
- 新生適應性成長小組計劃書
- 08SS523建筑小區(qū)塑料排水檢查井
- 教學評一體化的教學案例 課件
- 父親去世訃告范文(通用12篇)
- 人教版八年級上Unit 2How often do you exercise Section A(Grammar Focus-3c)
- 導讀工作總結優(yōu)秀范文5篇
- SB/T 10851-2012會議中心運營服務規(guī)范
評論
0/150
提交評論