QT——模型/視圖(model/view)

來源:互聯網
上載者:User

標籤:style   blog   http   color   get   使用   

資料項目中引入模型/視圖架構,可以方便的將資料與表現層分開。

-------------------------------------

模型Model:一般來說,Model裡面並不真正儲存資料(資料少的話也可以直接儲存在Model裡),只是負責從諸如磁碟檔案,資料庫,網路通訊等獲得來源資料,並提供給View,View對資料進行修改,然後再通過Model更新來源資料。
Model 另一個重要工作時為來源資料添加索引(ModelIndex)。列表形式採用row/colum編號,樹形式為建立父子間的層次關係而多添加了一個ParentIndex索引。
當View需要顯示資料或者需要View中的指定資料項目時,通過模組索引(ModelIndex)從Model中擷取資料,如果View中添加了自訂“委託”,要通過調用mapFromSource 返回和源Model相映射的“委託模組”的索引來擷取資料。

-------------------------------------

為每個視圖都提供了一個預設的委託——可以使用自訂的委託來替換顯示每一項,並為可編輯項提供一個合適的編輯器。

-------------------------------------

模型:用於儲存資料項目(data item)。

純粹的視圖組件:QListView、QColumnView、QTableView、QColumnView和QTreeView,必須為視圖提供一個模型與之配合。

-------------------------------------

便利的視窗組件:QListWidget、QTableview和QTreeWidget,都有自己的內建模型並能直接使用。

QComboBox:既是一個便利視窗組件也是一個視圖組件,即既能直接使用(內建的模型),也可當做視圖(外部提供合適模型)。

-------------------------------------

QStyledItemDelegate委託:所有的標準視圖都提供了一個預設的QStyledItemDelegate委託(顯示視圖中各個項並為可編輯的項提供一個合適的編輯器)。可以自訂委託,控制視圖中的各個項的顯示和編輯。



-------------------------------------

對於有數百或數千個項的資料集,假設資料集在任何時候僅僅顯示在一個組件中,那麼選擇便利視窗組件(內建模型視圖組件)比較合適。

-------------------------------------

儘管有統一的API,但仍有兩種不同類型的模型:行列特性表格模型和父子關係的樹模型。

-------------------------------------

QStandardItemModel:是一個可被當成列表模型、表格模型或樹模型來使用的通用模型。它提供了一個基於項的API。對於能夠直接把資料恰好填充入列表、表格或樹模型的各個資料項目中,並能夠直接使用或僅需做微小改動即可的情況,使用QStandardItemModel是理想的選擇。

QAbstractTableModel:不儲存資料,使用者需要從這些類派生出子類,並在子類中定義某種資料結構來儲存資料。與此不同,類QStandardItemModel負責儲存資料,每個資料項目被表示為類QStandardItem的對象。

QStandardItem資料項目:一個資料項目由若干個『角色/*字型、顏色等資訊*/,資料子項』對組成,該類負責儲存、訪問這些資料。該類的內部定義了一個類型為QVector的容器,每個容器元素本質上存放一個『角色,資料子項』對,且各個角色可能對應具有不同類型的資料子項。

void setData ( const QVariant & value, int role)//將『role, value』對存入QStandardItem對象

QVariant data ( int role = ) const      //讀取角色role對應的資料子項

QStandardItemModel將類QStandardItem表示的資料項目組織起來,形成列表、表格、樹甚至更複雜的資料結構。

QStandardItemModel提供了一群組成員函數:添加資料項目appendRow()/*資料集為列表形式*/,更改資料項目或刪除資料項目。

void QStandardItemModel::appendRow(const QList<QStandardItem *> & items)

-------------------------------------

QSortFilterProxyModel代理:過濾資料,擁有“防火牆”的作用,限制輸出到View中進行顯示的資料。代理處理完資料,不是直接交給委託,而是交給View,View再負責傳遞給Item,Item再通過委託顯示特定的樣式。(代理->視圖->委託->顯示)

voidQSortFilterProxyModel::setSourceModel(QAbstractItemModel * sourceModel) 

--------------------------------------

QStyledItemDelegate委託處理過程(Item預設使用textedit顯示資料):


-------------------------------------

View通過ModelIndex從model中擷取資料:
QVariant QAbstractProxyModel::data(const QModelIndex & proxyIndex, int role = Qt::DisplayRole) const
當Model中的data變化時,自動發dataChanged signal給所有的view以便它們更新。

View修改Model中對應ModelIndex的資料:
bool QAbstractProxyModel::setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole)

View負責組織資料並顯示,但真正的顯示工作交給代理delegate,代理負責最終的顯示資料和處理使用者互動的工作。
------------------------------------

通過代理delegate編輯並顯示資料項目的過程:
當通過雙擊滑鼠或斷行符號等操作觸發了View的edit trigger時,Delegate會建立一個合適的widget
(如line edit或combo box等)處理使用者的輸入,使用者編輯完成以後發射commitData“編輯完成訊號”,
delegate通過setModelData將更新Model中的資料。
1)void paint(QPainter *painter, const QStyleOptionViewItem &option,  //View通過delegate重繪Item、渲染內容
               const QModelIndex &index) const;
------------------------------------

2)QWidget *createEditor(QWidget *parent,//建立修改資料編輯器
                          const QStyleOptionViewItem &option,
                          const QModelIndex &index) const;//QModelIndex選擇需要進行渲染的列
void setEditorData(QWidget *editor,       //為editor提供編輯的未經處理資料
                       const QModelIndex &index) const;
//當使用者開始編輯時,視圖首先調用 委託的createEditor( ) 建立一個編輯器,然後調用 setEditorData( ) 
並使用當前資料項目 Item 中的資料初始化編輯器。

------------------------------------
//當使用者點擊斷行符號,或者從 QTimeEidt 等控制項上失去輸入焦點後,editingFinished() 訊號就發送出來,
並且 commitAndColseEditor() 槽函數被調用。
connect( ..., SIGNAL(editingFinished()), ..., SLOT(CommitAndCloseEditor()) );
3)void ItemDelegate::CommitAndCloseEditor()
{
    //QObject::sender()   Returns a pointer to the object that sent the signal
    QTimeEdit *editor = qobject_cast<QTimeEdit *>(sender());    //使用 sender() 來獲得編輯器


    emit commitData( editor );//發送commitData() 訊號提醒視圖有一個已編輯好的資料需要更新了
    emit closeEditor( editor );//發送closeEditor( ) 訊號通知視圖編輯控制項不需要了,模型刪除該編輯器
}
--------------------------------------

//擷取編輯器中的資料並儲存到指定模組索引的Model中
4)void setModelData(QWidget *editor, QAbstractItemModel *model,
                      const QModelIndex &index) const;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.