Qt-5開發(fā)及實例-第8章-Qt-5模型-視圖結(jié)構(gòu)課件_第1頁
Qt-5開發(fā)及實例-第8章-Qt-5模型-視圖結(jié)構(gòu)課件_第2頁
Qt-5開發(fā)及實例-第8章-Qt-5模型-視圖結(jié)構(gòu)課件_第3頁
Qt-5開發(fā)及實例-第8章-Qt-5模型-視圖結(jié)構(gòu)課件_第4頁
Qt-5開發(fā)及實例-第8章-Qt-5模型-視圖結(jié)構(gòu)課件_第5頁
已閱讀5頁,還剩101頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第8章

Qt5模型/視圖結(jié)構(gòu)——概

述第8章Qt5模型/視圖結(jié)構(gòu)——概述Qt5模型/視圖結(jié)構(gòu)Qt的模型/視圖結(jié)構(gòu)分為三部分:模型(Model)、視圖(View)和代理(Delegate)。其中,模型與數(shù)據(jù)源通信,并為其他部件提供接口;而視圖從模型中獲得用來引用數(shù)據(jù)條目的模型索引(ModelIndex)。在視圖中,代理負責(zé)繪制數(shù)據(jù)條目,當(dāng)編輯條目時,代理和模型直接進行通信。模型/視圖/代理之間通過信號和槽進行通信,如圖8.1所示。

數(shù)據(jù)發(fā)生改變時,模型發(fā)出信號通知視圖。

用戶對界面進行操作,視圖發(fā)出信號。

代理發(fā)出信號告知模型和視圖編輯器目前的狀態(tài)。Qt5模型/視圖結(jié)構(gòu)Qt的模型/視圖結(jié)構(gòu)分為三部分:模型(21.模型(Model)2.視圖(View)3.代理(Delegate)01基

念1.模型(Model)2.視圖(View)3.代理(Dele3基

念1.模型(Model)InterView框架中的所有模型都基于抽象基類QAbstractItemModel,此類由QProxyModel、QAbstractListModel、QAbstractTableModel、QAbstractProxyModel、QDirModel、QFileSystemModel、QHelpContentModel和QStandardItemModel類繼承。其中,QAbstractListModel類和QAbstract

TableModel類是列表和表格模型的抽象基類,如果需要實現(xiàn)列表或表格模型,則應(yīng)從這兩個類繼承。完成QStringList存儲的QStringListModel類繼承自QAbstractListModel類,而與數(shù)據(jù)庫有關(guān)的QSqlQueryModel類繼承自QAbstractTableModel類;QAbstractProxyModel類是代理模型的抽象類;QDirModel類是文件和目錄的存儲模型。2.視圖(View)InterView框架中的所有視圖都基于抽象基類QAbstractItemView,此類由QColumnView、QHeaderView、QListView、QTableView和QTreeView類繼承。其中,QListView類由QUndoView類和QListWidget類繼承;QTableView類由QTableWidget類繼承;QTreeView類由QTreeWidget類繼承。而QListWidget類、QTableWidget類和QTreeWidget類實際上已經(jīng)包含了數(shù)據(jù),是模型/視圖集成在一起的類。3.代理(Delegate)InterView框架中的所有代理都基于抽象基類QAbstractItemDelegate,此類由QItemDelegate和

QStyledItemDelegate類繼承。其中,QItemDelegate類由表示數(shù)據(jù)庫中關(guān)系代理的QSqlRelationalDelegate類繼承。基本概念1.模型(Model)402“實例”模型/視圖類使用02“實例”模型/視圖類使用5“實例”模型/視圖類使用【例】(簡單)(CH801)實現(xiàn)一個簡單的文件目錄瀏覽器,完成效果如圖8.2所示。創(chuàng)建工程“DirModeE”,其源文件“main.cpp”中的具體代碼。“實例”模型/視圖類使用【例】(簡單)(CH801)實現(xiàn)一個6其中,(a)QDirModelmodel:新建一個QDirModel對象,為數(shù)據(jù)訪問做準(zhǔn)備。QDirModel的創(chuàng)建還可以設(shè)置過濾器,即只有符合條件的文件或目錄才可被訪問。QDirModel類繼承自QAbstractItemModel類,為訪問本地文件系統(tǒng)提供數(shù)據(jù)模型。它提供新建、刪除、創(chuàng)建目錄等一系列與文件操作相關(guān)的函數(shù),此處只是用來顯示本地文件系統(tǒng)。(b)tree.setModel(&model):調(diào)用setModel()函數(shù)設(shè)置View對象的Model為QDirModel對象的model。(c)tree.setSelectionMode(QAbstractItemView::MultiSelection):設(shè)置QTreeView對象的選擇方式為多選。(d)list.setSelectionModel(tree.selectionModel()):設(shè)置QListView對象與QTreeView對象使用相同的選擇模型。(e)table.setSelectionModel(tree.selectionModel()):設(shè)置QTableView對象與QTreeView對象使用相同的選擇模型。(f)

QObject::connect(&tree,SIGNAL(doubleClicked(QModelIndex)),&list,SLOT(setRootIndex(QModelIndex)))、QObject::connect(&tree,SIGNAL(doubleClicked(QModelIndex)),&table,SLOT(setRootIndex(QModelIndex)));:為了實現(xiàn)雙擊QTreeView對象中的某個目錄時,QListView對象和QTableView對象中顯示此選定目錄下的所有文件和目錄,需要連接QTreeView對象的doubleClicked()信號與QListView對象和QTableView對象的setRootIndex()槽函數(shù)。最后運行效果如圖8.2所示。“實例”模型/視圖類使用其中,“實例”模型/視圖類使用7第8章

Qt5模型/視圖結(jié)構(gòu)——模型(Model)第8章Qt5模型/視圖結(jié)構(gòu)——模型(Model)模型(Model)【例】(難度一般)(CH802)通過實現(xiàn)將數(shù)值代碼轉(zhuǎn)換為文字的模型來介紹如何使用自定義模型。此模型中保存了不同軍種的各種武器,實現(xiàn)效果如圖8.3所示。模型(Model)【例】(難度一般)(CH802)通過實現(xiàn)將9模型(Model)具體操作步驟如下。(1)ModelEx類繼承自QAbstractTableModel類,頭文件“modelex.h”中的具體代碼如下:#include<QAbstractTableModel>#include<QVector>#include<QMap>#include<QStringList>classModelEx:publicQAbstractTableModel{public:explicitModelEx(QObject*parent=0);//虛函數(shù)聲明

//(a)virtualintrowCount(constQModelIndex&parent=QModelIndex())const;virtualintcolumnCount(constQModelIndex&parent=QModelIndex())const;QVariantdata(constQModelIndex&index,introle)const;QVariantheaderData(intsection,Qt::Orientationorientation,introle)const;signals:publicslots:private:QVector<short>army;QVector<short>weaponType;QMap<short,QString>armyMap; //使用QMap數(shù)據(jù)結(jié)構(gòu)保存“數(shù)值—文字”的映射QMap<short,QString>weaponTypeMap;QStringListweapon;QStringListheader;voidpopulateModel(); //完成表格數(shù)據(jù)的初始化填充};模型(Model)具體操作步驟如下。#include<QA10模型(Model)(2)源文件“modelex.cpp”中的具體代碼如下:#include"modelex.h"ModelEx::ModelEx(QObject*parent):QAbstractTableModel(parent){armyMap[1]=tr("空軍");armyMap[2]=tr("海軍");armyMap[3]=tr("陸軍");armyMap[4]=tr("海軍陸戰(zhàn)隊");weaponTypeMap[1]=tr("轟炸機");weaponTypeMap[2]=tr("戰(zhàn)斗機");weaponTypeMap[3]=tr("航空母艦");weaponTypeMap[4]=tr("驅(qū)逐艦");weaponTypeMap[5]=tr("直升機");weaponTypeMap[6]=tr("坦克");weaponTypeMap[7]=tr("兩棲攻擊艦");weaponTypeMap[8]=tr("兩棲戰(zhàn)車");populateModel();}模型(Model)(2)源文件“modelex.cpp”中的11模型(Model)populateModel()函數(shù)的具體實現(xiàn)代碼如下:voidModelEx::populateModel(){header<<tr("軍種")<<tr("種類")<<tr("武器");army<<1<<2<<3<<4<<2<<4<<3<<1;weaponType<<1<<3<<5<<7<<4<<8<<6<<2;weapon<<tr("B-2")<<tr("尼米茲級")<<tr("阿帕奇")<<tr("黃蜂級")<<tr("阿利伯克級")<<tr("AAAV")<<tr("M1A1")<<tr("F-22");}columnCount()函數(shù)中,因為模型的列固定為“3”,所以直接返回“3”。intModelEx::columnCount(constQModelIndex&parent)const{ return3; }rowCount()函數(shù)返回模型的行數(shù)。intModelEx::rowCount(constQModelIndex&parent)const{returnarmy.size();}模型(Model)populateModel()函數(shù)的具體實12模型(Model)data()函數(shù)返回指定索引的數(shù)據(jù),即將數(shù)值映射為文字。QVariantModelEx::data(constQModelIndex&index,introle)const{if(!index.isValid())returnQVariant();if(role==Qt::DisplayRole) //(a){switch(index.column()){case0:returnarmyMap[army[index.row()]];break;case1:returnweaponTypeMap[weaponType[index.row()]];break;case2:returnweapon[index.row()];default:returnQVariant();}}returnQVariant();}模型(Model)data()函數(shù)返回指定索引的數(shù)據(jù),即將數(shù)13模型(Model)表8.1列出了Item主要的角色及其描述。常

量描

述Qt::DisplayRole顯示文字Qt::DecorationRole繪制裝飾數(shù)據(jù)(通常是圖標(biāo))Qt::EditRole在編輯器中編輯的數(shù)據(jù)Qt::ToolTipRole工具提示Qt::StatusTipRole狀態(tài)欄提示Qt::WhatsThisRoleWhat’sThis文字Qt::SizeHintRole尺寸提示Qt::FontRole默認代理的繪制使用的字體Qt::TextAlignmentRole默認代理的對齊方式Qt::BackgroundRole默認代理的背景畫刷Qt::ForegroundRole默認代理的前景畫刷Qt::CheckStateRole默認代理的檢查框狀態(tài)Qt::UserRole用戶自定義的數(shù)據(jù)的起始位置模型(Model)表8.1列出了Item主要的角色及其描述。14模型(Model)headerData()函數(shù)返回固定的表頭數(shù)據(jù),設(shè)置水平表頭的標(biāo)題,具體代碼如下:QVariantModelEx::headerData(intsection,Qt::Orientationorientation,introle)const{if(role==Qt::DisplayRole&&orientation==Qt::Horizontal)returnheader[section];returnQAbstractTableModel::headerData(section,orientation,role);}模型(Model)headerData()函數(shù)返回固定的表頭15模型(Model)(3)在源文件“main.cpp”中,將模型和視圖關(guān)聯(lián),具體代碼如下:#include<QApplication>#include"modelex.h"#include<QTableView>intmain(intargc,char*argv[]){QApplicationa(argc,argv);ModelExmodelEx;QTableViewview;view.setModel(&modelEx);view.setWindowTitle(QObject::tr("modelEx"));view.resize(400,400);view.show();returna.exec();}(4)運行效果如圖8.3所示。模型(Model)(3)在源文件“main.cpp”中,將模16第8章

Qt5模型/視圖結(jié)構(gòu)——視圖(View)第8章Qt5模型/視圖結(jié)構(gòu)——視圖(View)視圖(View)【例】(難度中等)(CH803)通過利用自定義的View,實現(xiàn)一個對TableModel的表格數(shù)據(jù)進行顯示的柱狀統(tǒng)計圖例子,以此介紹如何應(yīng)用自定義的View。實現(xiàn)效果如圖8.4所示。視圖(View)【例】(難度中等)(CH803)通過利用自定18視圖(View)具體實現(xiàn)步驟如下。(1)完成主窗體,以便顯示View的內(nèi)容。MainWindow類繼承自QMainWindow類,作為主窗體。以下是頭文件“mainwindow.h”的具體代碼。#include<QMainWindow>#include<QStandardItemModel>#include<QTableView>#include<QMenuBar>#include<QMenu>#include<QAction>#include<QSplitter>classMainWindow:publicQMainWindow{Q_OBJECTpublic:MainWindow(QWidget*parent=0);~MainWindow();voidcreateAction();voidcreateMenu();voidsetupModel();voidsetupView();private:QMenu*fileMenu;QAction*openAct;QStandardItemModel*model;QTableView*table;QSplitter*splitter;};視圖(View)具體實現(xiàn)步驟如下。#include<QMa19視圖(View)(2)下面是源文件“mainwindow.cpp”中的具體代碼:#include"mainwindow.h"#include<QItemSelectionModel>MainWindow::MainWindow(QWidget*parent):QMainWindow(parent){createAction();createMenu();setupModel();setupView();setWindowTitle(tr("ViewExample"));resize(600,600);}MainWindow::~MainWindow(){}voidMainWindow::createAction(){openAct=newQAction(tr("打開"),this);}voidMainWindow::createMenu(){fileMenu=newQMenu(tr("文件"),this);fileMenu->addAction(openAct);menuBar()->addMenu(fileMenu);}視圖(View)(2)下面是源文件“mainwindow.c20視圖(View)setupModel()函數(shù)新建一個Model,并設(shè)置表頭數(shù)據(jù),其具體實現(xiàn)代碼如下:voidMainWindow::setupModel(){model=newQStandardItemModel(4,4,this);model->setHeaderData(0,Qt::Horizontal,tr("部門"));model->setHeaderData(1,Qt::Horizontal,tr("男"));model->setHeaderData(2,Qt::Horizontal,tr("女"));model->setHeaderData(3,Qt::Horizontal,tr("退休"));}視圖(View)setupModel()函數(shù)新建一個Mode21視圖(View)setupView()函數(shù)的具體實現(xiàn)代碼如下:voidMainWindow::setupView(){table=newQTableView; //新建一個QTableView對象table->setModel(model); //為QTableView對象設(shè)置相同的ModelQItemSelectionModel*selectionModel=newQItemSelectionModel(model);

//(a)table->setSelectionModel(selectionModel);connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,ItemSelection)),table,SLOT(selectionChanged(QItemSelection,QItemSelection))); //(b)splitter=newQSplitter;splitter->setOrientation(Qt::Vertical);splitter->addWidget(table);setCentralWidget(splitter);}其中,(a)QItemSelectionModel*selectionModel=newQItemSelectionModel(model):新建一個QItemSelectionModel對象作為QTableView對象使用的選擇模型。(b)connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,ItemSelection)),table,SLOT(selectionChanged(QItemSelection,QItemSelection))):連接選擇模型的selectionChanged()信號與QTableView對象的selectionChanged()槽函數(shù),以便使自定義的HistogramView對象中的選擇變化能夠反映到QTableView對象的顯示中。視圖(View)setupView()函數(shù)的具體實現(xiàn)代碼如下22視圖(View)(3)此時,運行效果如圖8.5所示。視圖(View)(3)此時,運行效果如圖8.5所示。23視圖(View)以上只是實現(xiàn)了簡單的主窗體框架顯示,還沒有完成事件。具體實現(xiàn)步驟如下。(1)在頭文件“mainwindow.h”中添加代碼如下:public:voidopenFile(QString);publicslots:voidslotOpen();(2)在源文件mainwindow.cpp中添加代碼如下:#include<QFileDialog>#include<QFile>#include<QTextStream>#include<QStringList>其中,在createAction()函數(shù)中添加代碼如下:connect(openAct,SIGNAL(triggered()),this,SLOT(slotOpen()));視圖(View)以上只是實現(xiàn)了簡單的主窗體框架顯示,還沒有完24視圖(View)slotOpen()槽函數(shù)完成打開標(biāo)準(zhǔn)文件對話框,具體代碼如下:voidMainWindow::slotOpen(){QStringname;name=QFileDialog::getOpenFileName(this,"打開",".","histogramfiles(*.txt)");if(!name.isEmpty())openFile(name);}openFile()函數(shù)完成打開所選的文件內(nèi)容,其具體實現(xiàn)代碼。新建一個文本文件,命名為“histogram.txt”,保存在項目D:\Qt\CH8\CH803\build-ViewEx-Desktop_Qt_5_11_1_MinGW_32bit-Debug目錄下,加載文件數(shù)據(jù)后的運行效果如圖8.6所示。視圖(View)slotOpen()槽函數(shù)完成打開標(biāo)準(zhǔn)文件對25視圖(View)具體實現(xiàn)步驟如下。(1)自定義HistogramView類繼承自QAbstractItemView類,用于對表格數(shù)據(jù)進行柱狀圖顯示。下面是頭文件“histogramview.h”的具體代碼。其中,(a)visualRect()、scrollTo()、indexAt()、moveCursor()、horizontalOffset()、verticalOffset()、isIndexHidden()、setSelection()和visualRegionForSelection():QAbstractItemView類中的純虛函數(shù)。這些純虛函數(shù)不一定都要實現(xiàn),可以根據(jù)需要選擇性地實現(xiàn),但一定要聲明。(b)QModelIndexindexAt(constQPoint&point)const:當(dāng)鼠標(biāo)在視圖中單擊或位置發(fā)生改變時被觸發(fā),它返回鼠標(biāo)所在點的QModelIndex值。(c)voidmousePressEvent(QMouseEvent*event):柱狀統(tǒng)計圖可以被鼠標(biāo)單擊選擇,選中后以不同的方式顯示。(d)

voidselectionChanged(constQItemSelection&selected,constQItemSelection&deselected):當(dāng)數(shù)據(jù)項選擇發(fā)生變化時,此槽函數(shù)將響應(yīng)。(e)voiddataChanged(constQModelIndex&topLeft,constQModelIndex&bottomRight):當(dāng)模型中的數(shù)據(jù)發(fā)生變更時,此槽函數(shù)將響應(yīng)。(f)voidsetSelection(constQRect&rect,QItemSelectionModel::SelectionFlagsflags):將位于QRect內(nèi)的數(shù)據(jù)項按照SelectionFlags(描述被選擇的數(shù)據(jù)項以何種方式進行更新)指定的方式進行更新。(g)QItemSelectionModel*selections:用于保存與視圖選擇項相關(guān)的內(nèi)容。(h)QList<QRegion>MRegionList:用于保存其中某一類型柱狀圖的區(qū)域范圍,而每個區(qū)域是QList中的一個值。視圖(View)具體實現(xiàn)步驟如下。26視圖(View)(2)源文件“histogramview.cpp”的具體代碼。其中,(a)QPainterpainter(viewport()):以viewport()作為繪圖設(shè)備新建一個QPainter對象。(b)if(selections->isSelected(index)){…}else{…}:使用不同畫刷顏色區(qū)別選中與未被選中的數(shù)據(jù)項。(c)painter.drawRect(QRect(posM,y0-male*10,width,male*10)):根據(jù)當(dāng)前數(shù)據(jù)項的值按比例繪制一個方形表示此數(shù)據(jù)項。(d)MRegionList.insert(row,regionM):將此數(shù)據(jù)所占據(jù)的區(qū)域保存到MRegionList列表中,為后面的數(shù)據(jù)項選擇做準(zhǔn)備。(e)從intposF=x0+30語句到posF+=50語句之間的代碼段:完成了表格第2列數(shù)據(jù)的柱狀統(tǒng)計圖的繪制。同樣,使用不同的畫刷顏色區(qū)別選中與未被選中的數(shù)據(jù)項,同時保存每個數(shù)據(jù)項所占的區(qū)域至FRegionList列表中。(f)從intposS=x0+40語句到posS+=50語句之間的代碼段:完成了表格第3列數(shù)據(jù)的柱狀統(tǒng)計圖的繪制。視圖(View)(2)源文件“histogramview.c27視圖(View)dataChanged()函數(shù)實現(xiàn)當(dāng)Model中的數(shù)據(jù)更改時,調(diào)用繪圖設(shè)備的update()函數(shù)進行更新,反映數(shù)據(jù)的變化。具體實現(xiàn)代碼如下:voidHistogramView::dataChanged(constQModelIndex&topLeft,constQModelIndex&bottomRight){QAbstractItemView::dataChanged(topLeft,bottomRight);viewport()->update();}setSelectionModel()函數(shù)為selections賦初值,具體代碼如下:voidHistogramView::setSelectionModel(QItemSelectionModel*selectionModel){selections=selectionModel;}視圖(View)dataChanged()函數(shù)實現(xiàn)當(dāng)Mode28視圖(View)(3)下面的工作是完成對選擇項的更新。selectionChanged()函數(shù)中完成當(dāng)數(shù)據(jù)項發(fā)生變化時調(diào)用update()函數(shù),重繪繪圖設(shè)備即可工作。此函數(shù)是將其他View中的操作引起的數(shù)據(jù)項選擇變化反映到自身View的顯示中。具體代碼如下:voidHistogramView::selectionChanged(constQItemSelection&selected,constQItemSelection&deselected){viewport()->update();}鼠標(biāo)按下事件函數(shù)mousePressEvent(),在調(diào)用setSelection()函數(shù)時確定鼠標(biāo)單擊點是否在某個數(shù)據(jù)項的區(qū)域內(nèi),并設(shè)置選擇項。具體代碼如下:voidHistogramView::mousePressEvent(QMouseEvent*event){QAbstractItemView::mousePressEvent(event);setSelection(QRect(event->pos().x(),event->pos().y(),1,1),QItemSelectionModel::SelectCurrent);}視圖(View)(3)下面的工作是完成對選擇項的更新。voi29視圖(View)setSelection()函數(shù)的具體代碼如下:voidHistogramView::setSelection(constQRect&rect,QItemSelectionModel::SelectionFlagsflags){introws=model()->rowCount(rootIndex()); //獲取總行數(shù)intcolumns=model()->columnCount(rootIndex()); //獲取總列數(shù)QModelIndexselectedIndex; //(a)for(introw=0;row<rows;++row) //(b){for(intcolumn=1;column<columns;++column){QModelIndexindex=model()->index(row,column,rootIndex());QRegionregion=itemRegion(index); //(c)if(!ersected(rect).isEmpty())selectedIndex=index;}}if(selectedIndex.isValid()) //(d)selections->select(selectedIndex,flags);else{QModelIndexnoIndex;selections->select(noIndex,flags);}}視圖(View)setSelection()函數(shù)的具體代碼如30視圖(View)其中,(a)QModelIndexselectedIndex:用于保存被選中的數(shù)據(jù)項的Index值。此處只實現(xiàn)用鼠標(biāo)單擊選擇,而沒有實現(xiàn)用鼠標(biāo)拖曳框選,因此,鼠標(biāo)動作只可能選中一個數(shù)據(jù)項。若需實現(xiàn)框選,則可使用QModelIndexList來保存所有被選中的數(shù)據(jù)項的Index值。(b)for(introw=0;row<rows;++row){for(intcolumn=1;column<columns;++column){…}}:確定在rect中是否含有數(shù)據(jù)項。此處采用遍歷的方式將每個數(shù)據(jù)項的區(qū)域與rect區(qū)域進行intersected操作,獲得兩者之間的交集。若此交集不為空,則說明此數(shù)據(jù)項被選中,將它的Index值賦給selectedIndex。(c)QRegionregion=itemRegion(index):返回指定index的數(shù)據(jù)項所占用的區(qū)域。(d)if(selectedIndex.isValid()){…}else{…}:完成select()函數(shù)的調(diào)用,即完成最后對選擇項的設(shè)置工作。select()函數(shù)是在實現(xiàn)setSelection()函數(shù)時必須調(diào)用的。視圖(View)其中,31視圖(View)indexAt()函數(shù)的具體內(nèi)容。其中,(a)foreach(region,MRegionList){…}:檢查當(dāng)前點是否處于第1列(男)數(shù)據(jù)的區(qū)域中。(b)foreach(region,FRegionList){…}:檢查當(dāng)前點是否處于第2列(女)數(shù)據(jù)的區(qū)域中。(c)foreach(region,SRegionList){…}:檢查當(dāng)前點是否處于第3列(合計)數(shù)據(jù)的區(qū)域中。由于本例未用到以下函數(shù)的功能,所以沒有實現(xiàn)具體內(nèi)容,但仍然要寫出函數(shù)體的框架,代碼如下:QRectHistogramView::visualRect(constQModelIndex&index)const{}voidHistogramView::scrollTo(constQModelIndex&index,ScrollHint){}QModelIndexHistogramView::moveCursor(QAbstractItemView::CursorActioncursorAction,Qt::KeyboardModifiersmodifiers){}intHistogramView::horizontalOffset()const{}intHistogramView::verticalOffset()const{}boolHistogramView::isIndexHidden(constQModelIndex&index)const{}QRegionHistogramView::visualRegionForSelection(constQItemSelection&selection)const{}視圖(View)indexAt()函數(shù)的具體內(nèi)容。QRect32視圖(View)itemRegion()函數(shù)的具體代碼如下:QRegionHistogramView::itemRegion(QModelIndexindex){QRegionregion;if(index.column()==1) //男region=MRegionList[index.row()];if(index.column()==2) //女region=FRegionList[index.row()];if(index.column()==3) //退休region=SRegionList[index.row()];returnregion;}視圖(View)itemRegion()函數(shù)的具體代碼如下:33視圖(View)(4)在頭文件“mainwindow.h”中添加代碼如下:#include"histogramview.h"private:HistogramView*histogram;(5)在源文件“mainwindow.cpp”中添加代碼,其中,setupView()函數(shù)的代碼修改。其中,(a)histogram->setSelectionModel(selectionModel):新建的QItemSelectionModel對象作為QTableView對象和HistogramView對象使用的選擇模型。(b)

connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),histogram,SLOT(selectionChanged(QItemSelection,QItemSelection))):連接選擇模型的selectionChanged()信號與HistogramView對象的selectionChanged()槽函數(shù),以便使QTableView對象中的選擇變化能夠反映到自定義的HistogramView對象的顯示中。(6)運行效果如圖8.4所示。視圖(View)(4)在頭文件“mainwindow.h”中34第8章

Qt5模型/視圖結(jié)構(gòu)——代理(Delegate)第8章Qt5模型/視圖結(jié)構(gòu)——代理(Delegate)代理(Delegate)【例】(難度中等)(CH804)利用Delegate設(shè)計表格中控件,如圖8.7所示。代理(Delegate)【例】(難度中等)(CH804)利用36代理(Delegate)實現(xiàn)步驟如下。(1)首先,加載表格數(shù)據(jù),以便后面的操作。源文件“main.cpp”中的具體代碼。(2)選擇“構(gòu)建”→“構(gòu)建項目"DateDelegate"”菜單項,首先按照如圖8.8所示的格式編輯本例所用的數(shù)據(jù)文件“test.txt”,保存在項目D:\Qt\CH8\CH804\build-DateDelegate-Desktop_Qt_5_11_1_MinGW_32bit-Debug目錄下,然后運行程序,效果如圖8.7所示。代理(Delegate)實現(xiàn)步驟如下。37代理(Delegate)(3)在圖8.7中,使用手動的方式實現(xiàn)對生日的錄入編輯。下面使用日歷編輯框QDateTimeEdit控件實現(xiàn)對生日的編輯,用自定義的Delegate來實現(xiàn)。(4)DateDelegate繼承自QItemDelegate類。頭文件“datedelegate.h”中的具體代碼如下:#include<QItemDelegate>classDateDelegate:publicQItemDelegate{Q_OBJECTpublic:DateDelegate(QObject*parent=0);QWidget*createEditor(QWidget*parent,constQStyleOptionViewItem&option,constQModelIndex&index)const; //(a)voidsetEditorData(QWidget*editor,constQModelIndex&index)const; //(b)voidsetModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndex&index)const; //將Delegate中對數(shù)據(jù)的改變更新至Model中voidupdateEditorGeometry(QWidget*editor,constQStyleOptionViewItem&option,constQModelIndex&index)const; //更新控件區(qū)的顯示};其中,(a)QWidget*createEditor(QWidget*parent,constQStyleOptionViewItem&option,constQModelIndex&index)const:完成創(chuàng)建控件的工作,創(chuàng)建由參數(shù)中的QModelIndex對象指定的表項數(shù)據(jù)的編輯控件,并對控件的內(nèi)容進行限定。(b)voidsetEditorData(QWidget*editor,constQModelIndex&index)const:設(shè)置控件顯示的數(shù)據(jù),將Model中的數(shù)據(jù)更新至Delegate中,相當(dāng)于一個初始化工作。代理(Delegate)(3)在圖8.7中,使用手動的方式實38代理(Delegate)(5)源文件“datedelegate.cpp”中的具體代碼如下:#include"datedelegate.h"#include<QDateTimeEdit>DateDelegate::DateDelegate(QObject*parent):QItemDelegate(parent){}createEditor()函數(shù)的具體實現(xiàn)代碼如下:QWidget*DateDelegate::createEditor(QWidget*parent,constQStyleOptionViewItem&/*option*/,constQModelIndex&/*index*/)const{QDateTimeEdit*editor=newQDateTimeEdit(parent); //(a)editor->setDisplayFormat("yyyy-MM-dd"); //(b)editor->setCalendarPopup(true); //(c)editor->installEventFilter(const_cast<DateDelegate*>(this));

//(d)returneditor;}其中,(a)QDateTimeEdit*editor=newQDateTimeEdit(parent):新建一個QDateTimeEdit對象作為編輯時的輸入控件。(b)editor->setDisplayFormat("yyyy-MM-dd"):設(shè)置該QDateTimeEdit對象的顯示格式為yyyy-MM-dd,此為ISO標(biāo)準(zhǔn)顯示方式。代理(Delegate)(5)源文件“datedelegat39代理(Delegate)日期的顯示格式有多種,可設(shè)定為:yy.MM.dd19.01.01d.MM.yyyy1.01.2019其中,y表示年,M表示月(必須大寫),d表示日。(c)editor->setCalendarPopup(true):設(shè)置日歷選擇的顯示以Popup的方式,即下拉菜單方式顯示。(d)editor->installEventFilter(const_cast<DateDelegate*>(this)):調(diào)用QObject類的installEventFilter()函數(shù)安裝事件過濾器,使DateDelegate能夠捕獲QDateTimeEdit對象的事件。代理(Delegate)日期的顯示格式有多種,可設(shè)定為:yy40代理(Delegate)setEditorData()函數(shù)的具體代碼如下:voidDateDelegate::setEditorData(QWidget*editor,constQModelIndex&index)const{QStringdateStr=index.model()->data(index).toString(); //(a)QDatedate=QDate::fromString(dateStr,Qt::ISODate); //(b)QDateTimeEdit*edit=static_cast<QDateTimeEdit*>(editor);//(c)edit->setDate(date); //設(shè)置控件的顯示數(shù)據(jù)}其中,(a)QStringdateStr=index.model()->data(index).toString():獲取指定index數(shù)據(jù)項的數(shù)據(jù)。調(diào)用QModelIndex的model()函數(shù)可獲得提供index的Model對象,data()函數(shù)返回的是一個QVariant對象,toString()函數(shù)將它轉(zhuǎn)換為一個QString類型數(shù)據(jù)。(b)QDatedate=QDate::fromString(dateStr,Qt::ISODate):通過QDate的fromString()函數(shù)將以QString類型表示的日期數(shù)據(jù)轉(zhuǎn)換為QDate類型。Qt::ISODate表示QDate類型的日期是以ISO格式保存的,這樣最終轉(zhuǎn)換獲得的QDate數(shù)據(jù)也是ISO格式,使控件顯示與表格顯示保持一致。(c)QDateTimeEdit*edit=static_cast<QDateTimeEdit*>(editor):將editor轉(zhuǎn)換為QDateTimeEdit對象,以獲得編輯控件的對象指針。代理(Delegate)setEditorData()函數(shù)的41代理(Delegate)setModelData()函數(shù)的具體代碼如下:voidDateDelegate::setModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndex&index)const{QDateTimeEdit*edit=static_cast<QDateTimeEdit*>(editor); //(a)QDatedate=edit->date(); //(b)model->setData(index,QVariant(date.toString(Qt::ISODate))); //(c)} 其中,(a)static_cast<QDateTimeEdit*>(editor):通過緊縮轉(zhuǎn)換獲得編輯控件的對象指針。(b)QDatedate=edit->date():獲得編輯控件中的數(shù)據(jù)更新。(c)model->setData(index,QVariant(date.toString(Qt::ISODate))):調(diào)用setData()函數(shù)將數(shù)據(jù)修改更新到Model中。updateEditorGeometry()函數(shù)的具體代碼如下:voidDateDelegate::updateEditorGeometry(QWidget*editor,constQStyleOptionViewItem&option,constQModelIndex&index)const{editor->setGeometry(option.rect);}代理(Delegate)setModelData()函數(shù)的具42代理(Delegate)(6)在“main.cpp”文件中添加如下代碼:#include"datedelegate.h"在語句tableView.setModel(&model);后面添加如下代碼:DateDelegatedateDelegate;tableView.setItemDelegateForColumn(1,&dateDelegate);(7)此時運行程序,雙擊第1行第2列,將顯示如圖8.9所示的日歷編輯框控件。代理(Delegate)(6)在“main.cpp”文件中添43代理(Delegate)下面使用下拉列表框QComboBox控件實現(xiàn)對職業(yè)類型的輸入編輯,使用自定義的Delegate實現(xiàn)。(1)ComboDelegate繼承自QItemDelegate類。頭文件“combodelegate.h”中的具體代碼如下:#include<QItemDelegate>classComboDelegate:publicQItemDelegate{Q_OBJECTpublic:ComboDelegate(QObject*parent=0);QWidget*createEditor(QWidget*parent,constQStyleOptionViewItem&option,constQModelIndex &index)const;voidsetEditorData(QWidget*editor,constQModelIndex&index)const;voidsetModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndex&index)const;voidupdateEditorGeometry(QWidget*editor,constQStyleOptionViewItem&option,constQModelIndex&index)const;};代理(Delegate)下面使用下拉列表框QComboBox44代理(Delegate)(2)源文件“combodelegate.cpp”中的具體代碼如下:#include"combodelegate.h"#include<QComboBox>ComboDelegate::ComboDelegate(QObject*parent):QItemDelegate(parent){}createEditor()函數(shù)中創(chuàng)建了一個QComboBox控件,并插入可顯示的條目,安裝事件過濾器。具體代碼如下:QWidget*ComboDelegate::createEditor(QWidget*parent,constQStyleOptionViewItem&/*option*/,constQModelIndex&/*index*/)const{QComboBox*editor=newQComboBox(parent);editor->addItem("工人");editor->addItem("農(nóng)民");editor->addItem("醫(yī)生");editor->addItem("律師");editor->addItem("軍人");editor->installEventFilter(const_cast<ComboDelegate*>(this));returneditor;}代理(Delegate)(2)源文件“combodelega45代理(Delegate)setEditorData()函數(shù)中更新了Delegate控件中的數(shù)據(jù)顯示,具體代碼如下:voidComboDelegate::setEditorData(QWidget*editor,constQModelIndex&index)const{QStringstr=index.model()->data(index).toString();QComboBox*box=static_cast<QComboBox*>(editor);inti=box->findText(str);box->setCurrentIndex(i);}setModelData()函數(shù)中更新了Model中的數(shù)據(jù),具體代碼如下:voidComboDelegate::setModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndex&index)const{QComboBox*box=static_cast<QComboBox*>(editor);QStringstr=box->currentText();model->setData(index,str);}代理(Delegate)setEditorData()函數(shù)中46代理(Delegate)updateEditorGeometry()函數(shù)的具體代碼如下:voidComboDelegate::updateEditorGeometry(QWidget*editor,constQStyleOptionViewItem&option,constQModelIndex&/*index*/)const{editor->setGeometry(option.rect);}在“main.cpp”文件中添加以下內(nèi)容:#include"combodelegate.h"在語句tableView.setModel(&model)的后面添加以下代碼:ComboDelegatecomboDelegate;tableView.setItemDelegateForColumn(2,&comboDelegate);代理(Delegate)updateEditorGeomet47代理(Delegate)此時運行程序,雙擊第1行第3列,顯示如圖8.10所示的下拉列表。代理(Delegate)此時運行程序,雙擊第1行第3列,顯示48代理(Delegate)下面使用QSpinBox控件實現(xiàn)對收入的輸入編輯,調(diào)用自定義的Delegate來實現(xiàn)。SpinDelegate類的實現(xiàn)與ComboDelegate類的實現(xiàn)類似,此處不再詳細講解。(1)頭文件“spindelegate.h”中的具體代碼如下:#include<QItemDelegate>classSpinDelegate:publicQItemDelegate{Q_OBJECTpublic:SpinDelegate(QObject*parent=0);QWidget*createEditor(QWidget*parent,constQStyleOptionViewItem&option,constQModelIndex&index)const;voidsetEditorData(QWidget*editor,constQModelIndex&index)const;voidsetModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndex&index)const;voidupdateEditorGeometry(QWidget*editor,constQStyleOptionViewItem&option,constQModelIndex&index)const;};代理(Delegate)下面使用QSpinBox控件實現(xiàn)對收49代理(Delegate)(2)源文件“spindelegate.cpp”中的具體代碼如下:#include"spindelegate.h"#include<QSpinBox>SpinDelegate::SpinDelegate(QObject*parent):QItemDelegate(parent){}createEditor()函數(shù)的具體實現(xiàn)代碼如下:QWidget*SpinDelegate::createEditor(QWidget*parent,constQStyleOptionViewItem&/*option*/,constQModelIndex&/*index*/)const{QSpinBox*editor=newQSpinBox(parent);editor->setRange(0,10000);editor->installEventFilter(const_cast<SpinDelegate*>(this));returneditor;}代理(Delegate)(2)源文件“spindelegat50代理(Delegate)setEditorData()函數(shù)的具體實現(xiàn)代碼如下:voidSpinDelegate::setEditorData(QWidget*editor,constQModelIndex&index)const{intvalue=index.model()->data(index).toInt();QSpinBox*box=static_cast<QSpinBox*>(editor);box->setValue(value);}setModelData()函數(shù)的具體實現(xiàn)代碼如下:voidSpinDelegate::setModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndex&index)const{QSpinBox*box=static_cast<QSpinBox*>(editor);intvalue=box->value();model->setData(index,value);}代理(Delegate)setEditorData()函數(shù)的51代理(Delegate)updateEditorGeometry()函數(shù)的具體實現(xiàn)代碼如下:voidSpinDelegate::updateEditorGeometry(QWidget*editor,constQStyleOptionViewItem&option,constQModelIndex&/*index*/)const{editor->setGeometry(option.rect);}代理(Delegate)updateEditorGeomet52(3)在“main.cpp”文件中添加代碼如下:#include"spindelegate.h"在語句tableView.setModel(&model)的后面添加內(nèi)容如下:SpinDelegatespinDelegate;tableView.setItemDelegateForColumn(3,&spinDelegate);(4)此時運行程序,雙擊第1行第4列后的效果如圖8.11所示。(3)在“main.cpp”文件中添加代碼如下:SpinDe53第8章

Qt5模型/視圖結(jié)構(gòu)——概

述第8章Qt5模型/視圖結(jié)構(gòu)——概述Qt5模型/視圖結(jié)構(gòu)Qt的模型/視圖結(jié)構(gòu)分為三部分:模型(Model)、視圖(View)和代理(Delegate)。其中,模型與數(shù)據(jù)源通信,并為其他部件提供接口;而視圖從模型中獲得用來引用數(shù)據(jù)條目的模型索引(ModelIndex)。在視圖中,代理負責(zé)繪制數(shù)據(jù)條目,當(dāng)編輯條目時,代理和模型直接進行通信。模型/視圖/代理之間通過信號和槽進行通信,如圖8.1所示。

數(shù)據(jù)發(fā)生改變時,模型發(fā)出信號通知視圖。

用戶對界面進行操作,視圖發(fā)出信號。

代理發(fā)出信號告知模型和視圖編輯器目前的狀態(tài)。Qt5模型/視圖結(jié)構(gòu)Qt的模型/視圖結(jié)構(gòu)分為三部分:模型(551.模型(Model)2.視圖(View)3.代理(Delegate)01基

念1.模型(Model)2.視圖(View)3.代理(Dele56基

念1.模型(Model)InterView框架中的所有模型都基于抽象基類QAbstractItemModel,此類由QProxyModel、QAbstractListModel、QAbstractTableModel、QAbstractProxyModel、QDirModel、QFileSystemModel、QHelpContentModel和QStandardItemModel類繼承。其中,QAbstractListModel類和QAbstract

TableModel類是列表和表格模型的抽象基類,如果需要實現(xiàn)列表或表格模型,則應(yīng)從這兩個類繼承。完成QStringList存儲的QStringListModel類繼承自QAbstractListModel類,而與數(shù)據(jù)庫有關(guān)的QSqlQueryModel類繼承自QAbstractTableModel類;QAbstractProxyModel類是代理模型的抽象類;QDirModel類是文件和目錄的存儲模型。2.視圖(View

溫馨提示

  • 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)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論