Qt_Model_View_學(xué)習(xí)筆記.doc_第1頁
Qt_Model_View_學(xué)習(xí)筆記.doc_第2頁
Qt_Model_View_學(xué)習(xí)筆記.doc_第3頁
Qt_Model_View_學(xué)習(xí)筆記.doc_第4頁
Qt_Model_View_學(xué)習(xí)筆記.doc_第5頁
已閱讀5頁,還剩17頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

Qt Model/View 學(xué)習(xí)筆記 介紹 Qt 4推出了一組新的item view類,它們使用model/view結(jié)構(gòu)來管理數(shù)據(jù)與表示層的關(guān)系。這種結(jié)構(gòu)帶來的功能上的分離給了開發(fā)人員更大的彈性來定制數(shù)據(jù)項的表示,它也提供一個標準的model接口,使得更多的數(shù)據(jù)源可以被這些item view使用。這里對model/view的結(jié)構(gòu)進行了描述,結(jié)構(gòu)中的每個組件都進行了解釋,給出了一些例子說明了提供的這些類如何使用。Model/View 結(jié)構(gòu)Model-View-Controller(MVC), 是從Smalltalk發(fā)展而來的一種設(shè)計模式,常被用于構(gòu)建用戶界面。經(jīng)典設(shè)計模式的著作中有這樣的描述:MVC 由三種對象組成。Model是應(yīng)用程序?qū)ο螅琕iew是它的屏幕表示,Controller定義了用戶界面如何對用戶輸入進行響應(yīng)。在MVC之前,用戶界面設(shè)計傾向于三者揉合在一起,MVC對它們進行了解耦,提高了靈活性與重用性。假如把view與controller結(jié)合在一起,結(jié)果就是model/view結(jié)構(gòu)。這個結(jié)構(gòu)依然是把數(shù)據(jù)存儲與數(shù)據(jù)表示進行了分離,它與MVC都基于同樣的思想,但它更簡單一些。這種分離使得在幾個不同的view上顯示同一個數(shù)據(jù)成為可能,也可以重新實現(xiàn)新的view,而不必改變底層的數(shù)據(jù)結(jié)構(gòu)。為了更靈活的對用戶輸入進行處理,引入了delegate這個概念。它的好處是,數(shù)據(jù)項的渲染與編程可以進行定制。如上圖所示,model與數(shù)據(jù)源通訊,并提供接口給結(jié)構(gòu)中的別的組件使用。通訊的性質(zhì)依賴于數(shù)據(jù)源的種類與model實現(xiàn)的方式。view從model獲取model indexes,后者是數(shù)據(jù)項的引用。通過把model indexes提供給model,view可以從數(shù)據(jù)源中獲取數(shù)據(jù)。在標準的views中,delegate會對數(shù)據(jù)項進行渲染,當某個數(shù)據(jù)項被選中時,delegate通過model indexes與model直接進行交流。總的來說,model/view 相關(guān)類可以被分成上面所提到的三組:models,views,delegates。這些組件通過抽象類來定義,它們提供了共同的接口,在某些情況下,還提供了缺省的實現(xiàn)。抽象類意味著需要子類化以提供完整的其他組件希望的功能。這也允許實現(xiàn)定制的組件。models,views,delegates之間通過信號,槽機制來進行通訊:從model發(fā)出的信號通知view數(shù)據(jù)源中的數(shù)據(jù)發(fā)生了改變。從view發(fā)出的信號提供了有關(guān)被顯示的數(shù)據(jù)項與用戶交互的信息。從delegate發(fā)生的信號被用于在編輯時通知model和view關(guān)于當前編輯器的狀態(tài)信息。Models所有的item models都基于QAbstractItemModel類,這個類定義了用于views和delegates訪問數(shù)據(jù)的接口。數(shù)據(jù)本身不必存儲在model,數(shù)據(jù)可被置于一個數(shù)據(jù)結(jié)構(gòu)或另外的類,文件,數(shù)據(jù)庫,或別的程序組件中。關(guān)于model的基本概念在Model Classes部分中描述。QAbstractItemModel提供給數(shù)據(jù)一個接口,它非常靈活,基本滿足views的需要,無論數(shù)據(jù)用以下任何樣的形式表現(xiàn),如tables,lists,trees。然而,當你重新實現(xiàn)一個model時,如果它基于table或list形式的數(shù)據(jù)結(jié)構(gòu),最好從QAbstractListModel,QAbstractTableModel開始做起,因為它們提供了適當?shù)某R?guī)功能的缺省實現(xiàn)。這些類可以被子類化以支持特殊的定制需求。子類化model的過程在Create New Model部分討論QT提供了一些現(xiàn)成的models用于處理數(shù)據(jù)項:QStringListModel 用于存儲簡單的QString列表。QStandardItemModel 管理復(fù)雜的樹型結(jié)構(gòu)數(shù)據(jù)項,每項都可以包含任意數(shù)據(jù)。QDirModel 提供本地文件系統(tǒng)中的文件與目錄信息。QSqlQueryModel, QSqlTableModel,QSqlRelationTableModel用來訪問數(shù)據(jù)庫。假如這些標準Model不滿足你的需要,你應(yīng)該子類化QAbstractItemModel,QAbstractListModel或是QAbstractTableModel來定制。Views不同的view都完整實現(xiàn)了各自的功能:QListView把數(shù)據(jù)顯示為一個列表,QTableView把Model 中的數(shù)據(jù)以table的形式表現(xiàn),QTreeView 用具有層次結(jié)構(gòu)的列表來顯示model中的數(shù)據(jù)。這些類都基于QAbstractItemView抽象基類,盡管這些類都是現(xiàn)成的,完整的進行了實現(xiàn),但它們都可以用于子類化以便滿足定制需求。DelegatesQAbstractItemDelegate 是model/view架構(gòu)中的用于delegate的抽象基類。缺省的delegate實現(xiàn)在QItemDelegate類中提供。它可以用于Qt標準views的缺省 delegate.排序在model/view架構(gòu)中,有兩種方法進行排序,選擇哪種方法依賴于你的底層Model。假如你的model是可排序的,也就是它重新實現(xiàn)了QAbstractItemModel:sort()函數(shù),QTableView與QTreeView都提供了API,允許你以編程的方式對Model數(shù)據(jù)進行排序。另外,你也可以進行交互方式下的排序(例如,允許用戶通過點擊view表頭的方式對數(shù)據(jù)進行排序),可以這樣做:把QHeaderView:sectionClicked()信號與QTableView:sortByColum()槽或QTreeView:sortByColumn()槽進行聯(lián)結(jié)就好了。另一種方法是,假如你的model沒有提供需要的接口或是你想用list view表示數(shù)據(jù),可以用一個代理model在用view表示數(shù)據(jù)之前對你的model數(shù)據(jù)結(jié)構(gòu)進行轉(zhuǎn)換。便利類許多便利類都源于標準的view類,它們方便了那些使用Qt中基于項的view與table類,它們不應(yīng)該被子類化,它們只是為Qt 3的等價類提供一個熟悉的接口。這些類有QListWidget,QTreeWidget,QTableWidget,它們提供了如Qt 3中的QListBox, QlistView,QTable相似的行為。這些類比View類缺少靈活性,不能用于任意的models,推介使用model/view的方法處理數(shù)據(jù)。介紹Qt提供了兩個標準的models:QStandardItemModel和QDirModel。QStandardItemModel是一個多用途的model,可用于表示list,table,tree views所需要的各種不同的數(shù)據(jù)結(jié)構(gòu)。這個model也持有數(shù)據(jù)。QDirModel維護相關(guān)的目錄內(nèi)容的信息,它本身不持有數(shù)據(jù),僅是對本地文件系統(tǒng)中的文件與目錄的描述。QDirModel是一個現(xiàn)成的model,很容易進行配置以用于現(xiàn)存的數(shù)據(jù),使用這個model,可以很好地展示如何給一個現(xiàn)成的view設(shè)定model,研究如何用model indexes來操縱數(shù)據(jù)。model與views的搭配使用QListView與QTreeView很適合與QDirModel搭配。下面的例子在tree view與list view顯示了相同的信息,QDirModel提供了目錄內(nèi)容數(shù)據(jù)。這兩個Views共享用戶選擇,因此每個被選擇的項在每個view中都會被高亮。先裝配出一個QDirModel以供使用,再創(chuàng)建views去顯示目錄的內(nèi)容。這給我展示了使用model的最簡單的方式。model的創(chuàng)建與使用都在main()函數(shù)中完成:int main(int argc, char *argv) QApplication app(argc, argv); QSplitter *splitter = new QSplitter; QDirModel *model = new QDirModel; /從缺省目錄創(chuàng)建數(shù)據(jù) QTreeView *tree = new QTreeView(splitter); tree-setModel(model); tree-setRootIndex(model-index(QDir:currentPath(); QListView *list = new QListView(splitter); list-setModel(model); list-setRootIndex(model-index(QDir:currentPath(); /配置一個view去顯示model中的數(shù)據(jù),只需要簡單地調(diào)用setModel(),并把目錄model作為參數(shù)傳遞 /setRootIndex()告訴views顯示哪個目錄的信息,這需要提供一個model index,然后用這個 /model index去model中去獲取數(shù)據(jù) /index()這個函數(shù)是QDirModel特有的,通過把一個目錄做為參數(shù),得到了需要的model index /其他的代碼只是窗口show出來,進入程序的事件循環(huán)就好了splitter-setWindowTitle(Two views onto the same directory model); splitter-show(); return app.exec();上面的例子并沒有展示如何處理數(shù)據(jù)項的選擇,這包括很多細節(jié),以后會提到。Model類基本概念在model/view構(gòu)架中,model為view和delegates使用數(shù)據(jù)提供了標準接口。在Qt中,標準接口QAbstractItemModel類中被定義。不管數(shù)據(jù)在底層以何種數(shù)據(jù)結(jié)構(gòu)存儲,QAabstractItemModel的子類會以層次結(jié)構(gòu)的形式來表示數(shù)據(jù),結(jié)構(gòu)中包含了數(shù)據(jù)項表。我們按這種約定來訪問model中的數(shù)據(jù)項,但這個約定不會對如何顯示這些數(shù)據(jù)有任何限制。數(shù)據(jù)發(fā)生改變時,model通過信號槽機制來通知關(guān)聯(lián)的views。Model Indexes為了使數(shù)據(jù)存儲與數(shù)據(jù)訪問分開,引入了model index的概念。通過model index,可以引用model中的數(shù)據(jù)項,Views和delegates都使用indexes來訪問數(shù)據(jù)項,然后再顯示出來。因此,只有model需要了解如何獲取數(shù)據(jù),被model管理的數(shù)據(jù)類型可以非常廣泛地被定義。Model indexes包含一個指向創(chuàng)建它們的model的指針,這會在配合多個model工作時避免混亂。QAbstractItemModel *model = index.model();model indexes提供了對一項數(shù)據(jù)信息的臨時引用,通過它可以訪問或是修改model中的數(shù)據(jù)。既然model有時會重新組織內(nèi)部的數(shù)據(jù)結(jié)構(gòu),這時model indexes便會失效,因此不應(yīng)該保存臨時的model indexes。假如需要一個對數(shù)據(jù)信息的長期的引用,那么應(yīng)該創(chuàng)建一個persistent model index。這個引用會保持更新。臨時的model indexes由QModelIndex提供,而具有持久能力的model indexes則由QPersistentModelIndex提供。在獲取對應(yīng)一個數(shù)據(jù)項的model index時,需要考慮有關(guān)于model的三個屬性:行數(shù),列數(shù),父項的model index。行與列在最基本的形式中,一個model可作為一個簡單的表來訪問,每個數(shù)據(jù)項由行,列數(shù)來定位。這必不意味著底層的數(shù)據(jù)用數(shù)組結(jié)構(gòu)來存儲。行和列的使用僅僅是一種約定,它允許組件之間相互通訊??梢酝ㄟ^指定model中的行列數(shù)來獲取任一項數(shù)據(jù),可以得到與數(shù)據(jù)項一一對應(yīng)的那個index。QModelIndex index = model-index(row, column, .);Model為簡單的,單級的數(shù)據(jù)結(jié)構(gòu)如list與tables提供了接口,它們?nèi)缟厦娲a所顯示的那樣,不再需要別的信息被提供。當我們在獲取一個model index時,我們需要提供另外的信息。上圖代表一個基本的table model,它的每一項用一對行列數(shù)來定位。通過行列數(shù),可以獲取代表一個數(shù)據(jù)項的model index . QModelIndex indexA = model-index(0, 0, QModelIndex();QModelIndex indexB = model-index(1, 1, QModelIndex();QModelIndex indexC = model-index(2, 1, QModelIndex();一個model的頂級項,由QModelIndex()取得,它們上式被用作父項。父項類似于表的接口在搭配使用table或list view時理想的,這種行列系統(tǒng)與view顯示的方式是確切匹配的。然則,像tree views這種結(jié)構(gòu)需要model提供更為靈活的接口來訪問數(shù)據(jù)項。每個數(shù)據(jù)項可能是別的項的父項,上級的項可以獲取下級項的列表。當獲取model中數(shù)據(jù)項的index時,我們必須指定關(guān)于數(shù)據(jù)項的父項的信息。在model外部,引用一個數(shù)據(jù)項的唯一方法就是通過model index,因此需要在求取model index時指定父項的信息。QModelIndex index = model-index(row, column, parent);上圖中,A項和C項作為model中頂層的兄弟項:QModelIndex indexA = model-index(0, 0, QModelIndex();QModelIndex indexC = model-index(2, 1, QModelIndex();A有許多孩子,它的一個孩子B用以下代碼獲?。篞ModelIndex indexB = model-index(1, 0, indexA);項角色model中的項可以作為各種角色來使用,這允許為不同的環(huán)境提供不同的數(shù)據(jù)。舉例來說,Qt:DisplayRole被用于訪問一個字符串,它作為文本會在view中顯示。典型地,每個數(shù)據(jù)項都可以為許多不同的角色提供數(shù)據(jù),標準的角色在Qt:ItemDataRole中定義。我們可以通過指定model index與角色來獲取我們需要的數(shù)據(jù):QVariant value = model-data(index, role);q角色指出了從model中引用哪種類型的數(shù)據(jù)。views可以用不同的形式顯示角色,因此為每個角色提供正確的信息是非常重要的。通過為每個角色提供適當數(shù)據(jù),model也為views和delegates提供了暗示,如何正確地把這些數(shù)據(jù)項顯給用戶。不同的views可以自由地解析或忽略這些數(shù)據(jù)信息,對于特殊的場合,也可以定義一些附加的角色。概念總結(jié):1,Model indexes為views與delegages提供model中數(shù)據(jù)項定位的信息,它與底層的數(shù)據(jù)結(jié)構(gòu)無關(guān)。2,通過指定行,列數(shù),父項的model index來引用數(shù)據(jù)項。3,依照別的組件的要求,model indexes被model構(gòu)建。4,使用index()時,如果指定了有效的父項的model index,那么返回得到的model index對應(yīng)于父項的某個孩子。5,使用index()時,如果指定了無效的父項的model index,那么返回得到的model index對應(yīng)于頂層項的某個孩子。6, 角色對一個數(shù)據(jù)項包含的不同類型的數(shù)據(jù)給出了區(qū)分。使用Model IndexesQDirModel *model = new QDirModel; QModelIndex parentIndex = model-index(QDir:currentPath(); int numRows = model-rowCount(parentIndex);for (int row = 0; row index(row, 0, parentIndex); tring text = model-data(index, Qt:DisplayRole).toString(); / Display the text in a widget. 以上的例子說明了從model中獲取數(shù)據(jù)的基本原則:1,model的尺寸可以從rowCount()與columnCount()中得出。這些函數(shù)通常都需要一個表示父項的model index。2,model indexes用來從model中訪問數(shù)據(jù)項,數(shù)據(jù)項用行,列,父項model index定位。3, 為了訪問model頂層項,可以使用QModelIndex()指定。4, 數(shù)據(jù)項為不同的角色提供不同的數(shù)據(jù)。為了獲取數(shù)據(jù),除了model index之外,還要指定角色。創(chuàng)建新的Models介紹model/view組件之間功能的分離,允許創(chuàng)建model利用現(xiàn)成的views。這也可以使用標準的功能 圖形用戶接口組件像QListView,QTableView和QTreeView來顯示來自各種數(shù)據(jù)源的數(shù)據(jù)為。QAbstractListModel類提供了非常靈活的接口,允許數(shù)據(jù)源以層次結(jié)構(gòu)的形式來管理信息,也允許以某種方式對數(shù)據(jù)進行插入、刪除、修改和存儲。它也提供了對拖拽操作的支持。QAbstractListModel與QAbstractTableModel為簡單的非層次結(jié)構(gòu)的數(shù)據(jù)提供了接口,對于比較簡單的list和table models來說,這是不錯的一個開始點。設(shè)計一個Model當我們?yōu)榇嬖诘臄?shù)據(jù)結(jié)構(gòu)新建一個model時,首先要考慮的問題是應(yīng)該選用哪種model來為這些數(shù)據(jù)提供接口。假如數(shù)據(jù)結(jié)構(gòu)可以用數(shù)據(jù)項的列表或表來表示,那么可以考慮子類化QAbstractListModel或QAbstractTableModel,既然這些類已經(jīng)合理地對許多功能提供缺省實現(xiàn)。然而,假如底層的數(shù)據(jù)結(jié)構(gòu)只能表示成具有層次結(jié)構(gòu)的樹型結(jié)構(gòu),那么必須得子類化QAbstractItemModel。無論底層的數(shù)據(jù)結(jié)構(gòu)采取何種形式,在特定的model中實現(xiàn)標準的QAbstractItemModel API總是一個不錯的主意,這使得可以使用更自然的方式對底層的數(shù)據(jù)結(jié)構(gòu)進行訪問。這也使得用數(shù)據(jù)構(gòu)建model 更為容易,其他的model/view組件也可以使用標準的API與之進行交互。一個只讀model示例這個示例實現(xiàn)了一個簡單的,非層次結(jié)構(gòu)的,只讀的數(shù)據(jù)model,它基于QStringistModel類。它有一個QStringList作為它內(nèi)部的數(shù)據(jù)源,只實現(xiàn)了一些必要的接口。為了簡單化,它子類化了QAbstractListModel,這個基類提供了合理的缺省行為,對外提供了比QAbstractItemModel更為簡單的接口。當我們實現(xiàn)一個model時,不要忘了QAbstractItemModel本身不存儲任何數(shù)據(jù),它僅僅提供了給views訪問數(shù)據(jù)的接口。class StringListModel : public QAbstractListModel Q_OBJECTpublic: StringListModel(const QStringList &strings, QObject *parent = 0) : QAbstractListModel(parent), stringList(strings) int rowCount(const QModelIndex &parent = QModelIndex() const; QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt:Orientation orientation, int role = Qt:DisplayRole) const;private: QStringList stringList;除了構(gòu)造函數(shù),我們僅需要實現(xiàn)兩個函數(shù):rowCount()返回model中的行數(shù),data()返回與特定model index對應(yīng)的數(shù)據(jù)項。具有良好行為的model也會實現(xiàn)headerData(),它返回tree和table views需要的,在標題中顯示的數(shù)據(jù)。因為這是一個非層次結(jié)構(gòu)的model,我們不必考慮父子關(guān)系。假如model具有層次結(jié)構(gòu),我們也應(yīng)該實現(xiàn)index()與parent()函數(shù)。Model的尺寸我們認為model中的行數(shù)與string list中的string數(shù)目一致:int StringListModel:rowCount(const QModelIndex &parent) const return stringList.count();在缺省情況下,從QAbstractListModel派生的model只具有一列,因此不需要實現(xiàn)columnCount()。Model 標題與數(shù)據(jù)QVariant StringListModel:data(const QModelIndex &index, int role) const if (!index.isValid() return QVariant(); if (index.row() = stringList.size() return QVariant(); if (role = Qt:DisplayRole) return stringList.at(index.row(); else return QVariant();QVariant StringListModel:headerData(int section, Qt:Orientation orientation, int role) const if (role != Qt:DisplayRole) return QVariant(); if (orientation = Qt:Horizontal) return QString(Column %1).arg(section); else return QString(Row %1).arg(section);一個數(shù)據(jù)項可能有多個角色,根據(jù)角色的不同輸出不同的數(shù)據(jù)。上例中,model中的數(shù)據(jù)項只有一個角色 ,DisplayRole,然而我們也可以重用提供給DisplayRole的數(shù)據(jù),作為別的角色使用,如我們可以作為ToolTipRole來用??删庉嫷膍odel上面我們演示了一個只讀的model,它只用于向用戶顯示,對于許多程序來說,可編輯的list model可能更有用。我們只需要給只讀的model提供另外兩個函數(shù)flags()與setData()的實現(xiàn)。下列函數(shù)聲明被添加到類定義中: Qt:ItemFlags flags(const QModelIndex &index) const; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt:EditRole);讓model可編輯delegate會在創(chuàng)建編輯器之前檢查數(shù)據(jù)項是否是可編輯的。model必須得讓delegate知道它的數(shù)據(jù)項是可編輯的。這可以通過為每一個數(shù)據(jù)項返回一個正確的標記得到,在本例中,我們假設(shè)所有的數(shù)據(jù)項都是可編輯可選擇的:Qt:ItemFlags StringListModel:flags(const QModelIndex &index) const if (!index.isValid() return Qt:ItemIsEnabled; return QAbstractItemModel:flags(index) | Qt:ItemIsEditable;我們不必知道delegate執(zhí)行怎樣實際的編輯處理過程,我們只需提供給delegate一個方法,delegate會使用它對model中的數(shù)據(jù)進行設(shè)置。這個特殊的函數(shù)就是setData():bool StringListModel:setData(const QModelIndex &index, const QVariant &value, int role) if (index.isValid() & role = Qt:EditRole) stringList.replace(index.row(), value.toString(); emit dataChanged(index, index); return true; return false;當數(shù)據(jù)被設(shè)置后,model必須得讓views知道一些數(shù)據(jù)發(fā)生了變化,這可通過發(fā)射一個dataChanged() 信號實現(xiàn)。因為只有一個數(shù)據(jù)項發(fā)生了變化,因此在信號中說明的變化范圍只限于一個model index。插入,刪除行在model中改變行數(shù)與列數(shù)是可能的。當然在本列中,只考慮行的情況,我們只需要重新實現(xiàn)插入、刪除的函數(shù)就可以了,下面應(yīng)在類定義中聲明: bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex(); bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex();既然model中的每行對應(yīng)于列表中的一個string,因此,insertRows()函數(shù)在string list 中指定位置插入一個空string,父index通常用于決定model中行列的位置,本例中只有一個單獨的頂級項,困此只需要在list中插入空string。bool StringListModel:insertRows(int position, int rows, const QModelIndex &parent) beginInsertRows(QModelIndex(), position, position+rows-1);/這里為什么用一個for 語句,一直想不通,就是不用for語句功能也是實現(xiàn)了。 for (int row = 0; row rows; +row) stringList.insert(position, ); endInsertRows(); return true;beginInsertRows()通知其他組件行數(shù)將會改變。endInsertRows()對操作進行確認與通知。返回true表示成功。刪除操作與插入操作類似:bool StringListModel:removeRows(int position, int rows, const QModelIndex &parent) beginRemoveRows(QModelIndex(), position, position+rows-1); for (int row = 0; row rows; +row) stringList.removeAt(position); endRemoveRows(); return true;View 類概念在model/view架構(gòu)中,view從model中獲得數(shù)據(jù)項然后顯示給用戶。數(shù)據(jù)顯示的方式不必與model提供的表示方式相同,可以與底層存儲數(shù)據(jù)項的數(shù)據(jù)結(jié)構(gòu)完全不同。內(nèi)容與顯式的分離是通過由QAbstractItemModel提供的標準模型接口,由QAsbstractItemview提供的標準視圖接口共同實現(xiàn)的。普遍使用model index來表示數(shù)據(jù)項。view負責管理從model中讀取的數(shù)據(jù)的外觀布局。它們自己可以去渲染每個數(shù)據(jù)項,也可以利用delegate來既處理渲染又進行編輯。除了顯示數(shù)據(jù),views也處理數(shù)據(jù)項的導(dǎo)航,參與有關(guān)于數(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ù)。從 model中獲取數(shù)據(jù)的函數(shù)是QabstractItemModel:headerDate(),一般總是以表單的形式中顯示標題信息??梢詮腝HeaderView子類化,以實現(xiàn)更為復(fù)雜的定制化需求。使用現(xiàn)成的viewQt提供了三個現(xiàn)成的view 類,它們能夠以用戶熟悉的方式顯示model中的數(shù)據(jù)。QListView把model中的數(shù)據(jù)項以一個簡單的列表的形式顯示,或是以經(jīng)典的圖標視圖的形式顯示。QTreeView把model中的數(shù)據(jù)項作為具有層次結(jié)構(gòu)的列表的形式顯示,它允許以緊湊的深度嵌套的結(jié)構(gòu)進行顯示。QTableView卻是把model中的數(shù)據(jù)項以表格的形式展現(xiàn),更像是一個電子表格應(yīng)用程序的外觀布局。以上這些標準view的行為足以應(yīng)付大多數(shù)的應(yīng)用程序,它們也提供了一些基本的編輯功能,也可以定制特殊的需求。使用model以前的例子中創(chuàng)建過一個string list model,可以給它設(shè)置一些數(shù)據(jù),再創(chuàng)建一個view把model中的內(nèi)容展示出來:int main(int argc, char *argv)QApplication app(argc, argv);/ Unindented for quoting purposes:QStringList numbers;numbers One Two Three Four setModel(model); view-show(); return app.exec();view會渲染model中的內(nèi)容,通過model的接口來訪問它的數(shù)據(jù)。當用戶試圖編輯數(shù)據(jù)項時,view會使用缺省的delegate來提供一個編輯構(gòu)件。一個model,多個views為多個views提供相同的model是非常簡單的事情,只要為每個view設(shè)置相同的model。 QTableView *firstTableView = new QTableView; QTableView *secondTableView = new QTableView; firstTableView-setModel(model); secondTableView-setModel(model);在model/view架構(gòu)中信號、槽機制的使用意味著model中發(fā)生的改變會傳遞中聯(lián)結(jié)的所有view中,這保證了不管我們使用哪個view,訪問的都是同樣的一份數(shù)據(jù)。上面的圖展示了一個model上的兩個不同的views,盡管在不同的view中顯示的model中的數(shù)據(jù)是一致的,每個view都維護它們自己的內(nèi)部選擇模型,但有時候在某些情況下,共享一個選擇模型也是合理的。處理數(shù)據(jù)項的選擇view中數(shù)據(jù)項選擇機制由QItemSelectionModel類提供。所有標準的view缺省都構(gòu)建它們自己的選擇模型,以標準的方式與它們交互。選擇模型可以用selectionModel()函數(shù)取得,替代的選擇模型也可以通過setSelectionModel()來設(shè)置。當我們想在一個model上提供多個一致的views時,這種對選擇模型的控制能力非常有用。通常來講,除非你子類化一個model或view,你不必直接操縱selections的內(nèi)容。多個views之間共享選擇接著上邊的例子,我們可以這樣:secondTableView-setSelectionModel(firstTableView-selectionModel();現(xiàn)在所有views都在同樣的選擇模型上操作,數(shù)據(jù)與選擇項都保持同步。上面的例子中,兩個view的類型是相同的,假如這兩個view類型不同,那么所選擇的數(shù)據(jù)項在每個view中的表現(xiàn)形式會有很大的不同。例如,在一個table view中一個連續(xù)的選擇,在一個tree view中表現(xiàn)出來的可能會是幾個高亮的數(shù)據(jù)項片斷的組合。在views中選擇數(shù)據(jù)項概念用于新的view類中的選擇模型比Qt3中的模型有了很大的改進。它為基于model/view架構(gòu)的選擇提供了更為全面的描述。盡管對提供了的views來說,負責操縱選擇的標準類已經(jīng)足以應(yīng)付,但是你也可以創(chuàng)建特定的選擇模型來滿足你特殊的需求。關(guān)于在view被選擇的數(shù)據(jù)項的信息保持在QItemSelectionModel類的實例中。它也為每個獨立的model中的數(shù)據(jù)項維護model indexes信息,與任何views都關(guān)聯(lián)關(guān)系。既然一個model可用于多個views,那么在多個views之間共享選擇信息也是可以做到的,這使得多個views可以以一致的方式進行顯示。選擇由多個選擇范圍組成。通過僅僅記錄開始model indexes與結(jié)束model indexes,最大化地記錄了可以選擇的范圍。非連續(xù)選擇數(shù)據(jù)項由多個選擇范圍來描述。選擇模型記錄model indexes的集合來描述一個選擇。最近選擇的數(shù)據(jù)項被稱為current selection。應(yīng)用程序可以通過使用某種類型的選擇命令來修改選擇的效果。在進行選擇操作時,可以把QItemSelectionModel看成是model中所有數(shù)據(jù)項選擇狀態(tài)的一個記錄。一旦建立一個選擇模型,所有項的集合都可以選擇,撤消選擇,或者選擇狀態(tài)進行切換而不需要知道哪個數(shù)據(jù)項是否已經(jīng)被選擇過。所有被選擇的項的indexes在任何時候都可以得到,通過信號槽機制可以通知別的組件發(fā)生的變化。使用選擇模型標準view類提供了缺省的選擇模型,它們可以在大次數(shù)程序中使用。一個view中的選擇模型可以通過調(diào)用view的函數(shù)selectionModel()取得,也可以通過setSelectionModel()在多個views之間共享選擇模型,因此總的來說構(gòu)建一個新的模型一般情況不太必要。通過給QItemSelection指定一個model,一對model indexes,可以創(chuàng)建一個選擇。indexes的用法依賴于給定的model,這兩個indexes被解釋成選擇的區(qū)塊中的左上角項和右下角項。model中的項的選擇服從于選擇模型。選擇項構(gòu)建一個table model ,它有32個項,用一個table view進行顯示: TableModel *model = new TableModel(8, 4, &app); QTableView *table = new QTableView(0); table-setModel(model); QItemSelectionModel *selectionModel = table-selectionModel(); QModelIndex topLeft; QModelIndex bottomRight; topLeft = model-index(0, 0, QModelIndex(); bottomRight = model-index(5, 2, QModelIndex(); QItemSelection selection(topLeft, bottomRight); selectionModel-select(selection, QItemSelectionModel:Select);結(jié)果如下:讀取選擇狀態(tài) 存儲在選擇模型中indexes可以用selectionIndexes()函數(shù)來讀取。它返回一個未排序的model indexes列表,我們可以遍歷它,如果我們知道他們關(guān)聯(lián)于哪個model的話。 QModelIndexList indexes = selectionModel-selectedIndexes(); QModelIndex index; foreach(index, indexes) QString text = QString(%1,%2).arg(index.row().arg(index.column(); model-setData(index, text); 選擇模型在選擇發(fā)生變化時會發(fā)出信號。這用于通知別的組件包括整體與當前焦點項所發(fā)生的變化。我們可以連接selectionChanged()信號到一個槽,檢查當信號產(chǎn)生時哪些項被選擇或被取消選擇。這個槽被調(diào)用時帶有兩個參數(shù),它們都是QItemSelection對象,一個包含新被選擇的項,另一個包含新近被取消選擇的項。下面的代碼演示了給新選擇的項添加數(shù)據(jù)內(nèi)容,新近被取消選擇的項的內(nèi)容被清空。void MainWindow:updateSelection(const QItemSelection &selected, const QItemSelection &deselected) QModelIndex index; QModelIndexList items = selected.indexes(); foreach (index, items) QString text = QString(%1,%2).arg(index.row().arg(index.column(); model-setData(index, text); items = deselected.indexes(); foreach (index, items) model-setData(index, );也可以通過響應(yīng)currentChanged()信號來跟蹤當前焦點項.對應(yīng)的槽就有兩個接收參數(shù),一個表示之前的焦點,另一個表示當前的焦點。void MainWindow:changeCurrent(const QModelIndex ¤t, const QModelIndex &previous) statusBar()-showMessage( tr(Moved from (%1,%2) to (%3,%4) .arg(previous.row().arg(previous.column() .arg(current.row().arg(current.column();更新選擇選擇指令是通過選擇標志提供的,它被定義在QItemSelectionModel:SelectionFlag中。常用的有Select標記,Toggle標記,Deselect標記,Current標記,Clear標記,其意義一目了然。沿上面例子的結(jié)果執(zhí)行以下代碼: QItem

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論