Qt視圖模型框架初識(MVC)

聲明:本文章只是爲了自己學習寫的筆記,如需瞭解具體代碼示例或者詳細內容請參考<<QtCreator快速入門>>第十六章

一.首先來了解一下MVC(Model-View-Controller模型-視圖-控制)設計模式

MVC是一種起源於Smalltalk的設計模式,經常用於創建用戶界面,模型(Model)是應用對象用於表示數據;視圖是(View)是模型的用戶界面,用來顯示數據;控制(Controller)定義了用戶界面對用戶輸入的反應方式,在MVC之前都是將這三種組件集成在一起,MVC將他們分離,提高了靈活性和重用性,

二.更簡單的數據顯示框架--模型/視圖架構

(1)概要

將視圖和控制兩個組件結合起來就形成了模型/視圖架構,將數據的存儲和數據向用戶的展示進行了分離,提供了更爲簡單的框架.數據和界面進行分離,使得相同的數據在多個不同的視圖中顯示成爲可能,而且還可以創建新的視圖,而不需要改變底層的數據框架,爲了對用戶輸入進行靈活處理,還引入了委託(也被稱爲代理Delegate)的概念,使用它可以定製數據的渲染和編輯方式

整體架構如圖所示,其中模型與數據源進行通信,爲架構中的其他組件提供了接口.視圖從模型中獲得模型索引(Model Index),模型索引用來表示數據項,在標準的視圖中,委託渲染數據項,當編輯項目時,委託使用模型索引直接與模型進行通信

(2)組成

大體上,模型/視圖架構中的衆多類可以分爲3組:模型.視圖和委託,其中每一個組件都使用了一個抽象基類來定義,提供了一些通用接口和一些功能的默認實施,模型.視圖.委託之間使用信號和槽來實現通信:

[1]當數據源的數據發生改變時,模型發出信號告知視圖

[2]當用戶與顯示的項目交互時,視圖發出信號來提供交互信息

[3]當編輯項目時,委託發出信號,告知模型和視圖編輯器的狀態

1.模型

基於QAbstractItemModel類,提供接口,供視圖和委託來訪問數據.可以處理各種視圖,表現爲表格,列表和樹等形式

QAbstractListModel,QAbstractTableModel基於列表或者表格的數據結構,爲一些常見功能提供了默認的實現

一些現成的模型:

QStringListModel:用來存儲一個簡單的QString項目列表

QStandardItemModel:管理複雜的樹型數據項,每一個數據項可以包含任意的數據

QFileSystemModel 提供了本地文件系統中文件和目錄的信息

QSqlQueryModel.QSqlTableModel和QSqlRelationalTableModel用來訪問數據庫

如果默認的模型無法滿足要求可以子類化QAbstractItemModel,QAbstractListModel或者QAbstractTableModel來創建自定義的模型

2.視圖

幾種不同類型的視圖:

QListView將數據項顯示爲一個列表;

QTableView將模型中的數據顯示在一個表格中

QTreeView將模型的數據項顯示在具有層次的列表中

如果不能滿足要求可以集成QAbstractItemView自己實現

3.委託

委託的基類:QAbstractItemDelegate

默認的委託實現:QStyleItemDelegate

(3)模型類

[1]模型索引

每一塊可以同感模型獲取的數據都使用一個模型索引來表示,視圖和委託都使用這些索引來請求數據來顯示,模型索引由QModelIndex類提供,它是對一塊數據的臨時引用,可以用於檢索或者修改模型中的數據,獲取一個數據項的模型索引必須指定3個屬性:行號,列號和父項的模型索引

[2]行和列

數據項使用行號和列號來定位,但並不是都存儲在數組結構中,知識一種約定,確保組件間通信

行列號都是從0開始的,列表模型和表格模型都是以根項爲父項的,這些數據項都可以稱爲頂層數據項,父項的模型索引可以用QModelIndex()表示

[3]父項

在樹模型中,如果一個數據項不是頂層數據項,就要指定它的父項索引

[4]項角色

Qt::DisplayRole用來訪問可以作爲文本顯示在視圖中的字符串

數據項通常包含不同角色的數據,通常由枚舉類型Qt::ItemDataRole來定義,通過爲每個角色提供適當的項目數據,模型爲視圖和委託提供顯示,告訴它們數據應該怎樣展示給用戶

[5]自定義模型類,繼承QAbstractListModel,除了構造函數之外,只需要實現兩個函數rowCount()和data()

 

前者返回模型的行數,後者返回指定的模型索引的數據項,headerData(),可以在樹和表格視圖的表頭顯示一些內容,如果是層次結構的還需要index()和parent()函數

##1 添加編輯功能

爲了使模型可以編輯,需要更改data()函數,然後實現另外兩個函數:flags()和setData()

flags返回項目是否是可編輯的,返回一個標識

setData提供委託向模型中設置數據的一條途徑

數據被設置後發出dataChanged信號

還需要更改data()中判斷條件

##2插入和刪除行

需要重新實現isertRows()和removeRows()

,實現過程中首先調用beginInsertRows()告知其他組件指定的行將要發生改變,

改完之後調用endInsertRows

(4)視圖類

視圖包含了模型中的數據項並將它們呈現給用戶,而數據的表示方法可能與底層用於存儲數據項的數據結構完全不同,處理項目間的導航以及項目選擇的某些方面

 

##1處理項目選擇

視圖中被選擇的信息存儲在一個QItemSelectionModel實例中,這樣被選擇的項目模型索引就保持在一個獨立的模型中,與所有的視圖都是獨立的,一個模型上設置多個視圖時就可以實習請您多個視圖之間共享選擇

###1當前項目和被選擇的項目

###2使用選擇模型

屬於一個視圖的選擇模型可以使用這個視圖的selectionModel()函數來獲得,還可以在多個視圖之間使用setSelectionModel()函數來共享選擇模型,而且還可以在多個視圖之間使用setSelectionModel()函數來共享該選澤模型,所以一般是不需要重新構建一個選擇模型的

(5)委託類

爲了獲得更高的靈活性,交互可以由委託來執行,這些組件提供了輸入功能,也負責渲染一些視圖中的個別項目.

委託通過實現paint()和sizeHint()函數來使它們可以渲染自身的內容.簡單的基於部件的委託可以通過繼承QItemDelegate來實現,而不需要使用QAbstractItemDelegate,這樣

可以使用這些函數的默認實現,委託的編輯器可以通過兩種方式來實現,一種是使用部件來管理編輯過程,另一種是直接處理事件

(6)項目視圖的便捷類

QListWidget:提供了一個項目列表

QTreeWidget顯示了一個多層次的樹結構

QTableWidget提供了一個以項目作爲單元的表格,適合用於少量數據的存儲和顯示

三.其他內容

(1)代理模型

代理模型可以將一個模型中的數據進行排序或者過濾,然後提供給視圖進行顯示,QT中提供了QSortFilterProxyModel作爲標準的代理模型來完成模型中數據的排序和過濾,要使用一個代理模型,則只需要爲其設置源模型然後在視圖中使用該代理模型即可.

(2)數據-窗口映射器

數據窗口映射器QDataWidgetMapper類在數據模型的一個區域和一個窗口部件間提供了一個映射,這樣就可以實現在一個窗口上顯示和編輯一個模型中的一行數據

QDataWidgetMapper, toFirst()顯示模型中第一行數據,toPdevious()函數和toNext()函數顯示模型中上一行和下一行,還有一個toLast()函數可以顯示模型中最後一行的數據

總結:模型視圖框架是一個很複雜的知識框架,很難一次性掌握,剛開始學習不懂是正常的,需要把握住其核心:模型用來提供數據,視圖用來顯示數據,委託用來提供項目的特殊顯示以及編輯器.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章