Qt的模型/視圖結構分爲三部分:模型(Model)、視圖(View)和代理(Delegate)。其中,模型與數據源通信,併爲其他部件提供接口;而視圖從模型中獲得用來引用數據條目的模型索引(Model Index)。在視圖中,代理負責繪製數據條目,當編輯條目時,代理和模型直接進行通信。模型/視圖/代理之間通過信號和槽進行通信,
概述
基本概念
-
模型(model)
InterView框架中的所有模型都基於抽象基類QAbstractItemModel類,此類由QProxyModel、 QAbstractListModel、 QAbstractTableModel、QAbstractProxyModel、 QDirModel、 QFileSystemModel、QHelpContentModel 和 QStandardItemModel類繼承。其中, QAbstractListModel
類和QAbstractTableModel類是列表和表格模型的抽象基類,如果需要實現列表或表格模型,則應從這兩個類繼承。完成QStringList存儲的QStringListModel繼承自QAbstractListModel類,而與數據庫有關的QSqlQueryModel類繼承自QAbstractTableModel類; QAbstractProxyModel類是代理模型的抽象類;QDirModel類是文件和目錄的存儲模型。 -
視圖(view)
InterView框架中的所有視圖都基於抽象基類QAbstractItemView類,此類由QColumnView、 QHeaderView、 QListView、 QTableView和QTreeView類繼承。其中, QListView類由QUndoView類和QListWidget類繼承; QTableView類由QTableWidget類繼承; QTreeView類由QTreeWidget類繼承。而QListWidget類、QTableWidget類和QTreeWidget類實際上已經包含了數據,是模型/視圖集成在一起的類。 -
代理(delegate)
InterView框架中的所有代理都基於抽象基類QAbstractItemDelegate類,此類由QItemDelegate 和 QStyledItemDelegate類繼承。其中, QItemDelegate類由表示數據庫中關係代理的QSqlRelationalDelegate類繼承。
簡單文件目錄瀏覽器【簡單示例】
簡單實現一個文件目錄瀏覽器。只需要編輯main.cpp文件在項目文件中即可。
- main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QAbstractItemModel>
#include <QAbstractItemView>
#include <QItemSelectionModel>
#include <QDirModel>
#include <QTreeView>
#include <QListView>
#include <QTableView>
#include <QSplitter>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//新建一個QDirModel對象,爲數據訪問做準備,此外還可以設置過濾器。
//QDirmodel爲訪問本地文件系統提供數據模型,提供了新建、刪除、創建目錄等一系列與文件操作相關的函數。
QDirModel model;
/* 新建三種不同的View對象,以便文件目錄可以以三種不同的方式顯示 */
QTreeView tree;
QListView list;
QTableView table;
//調用setModel函數設置View對象的model爲QDirmodel。
tree.setModel(&model);
list.setModel(&model);
table.setModel(&model);
//設置QTreeView對象的選擇方式爲多選方式。
tree.setSelectionMode(QAbstractItemView::MultiSelection);
//設置QListView對象與QTreeView對象使用相同的選擇模型。
list.setSelectionModel(tree.selectionModel());
//設置QTableView對象與QTreeView對象使用相同的選擇模型。
table.setSelectionModel(tree.selectionModel());
QObject::connect(&tree,SIGNAL(doubleClicked(QModelIndex)),&list,
SLOT(setRootIndex(QModelIndex)));
//實現雙機對象中某一目錄時顯示此目錄下的所以文件和目錄,需要連接QTreeView對象的doubleClicked信號
//與QListView對象和QTableView對象的setRootIndex槽函數。
QObject::connect(&tree,SIGNAL(doubleClicked(QModelIndex)),&table,
SLOT(setRootIndex(QModelIndex)));
QSplitter *splitter = new QSplitter;
splitter->addWidget(&tree);
splitter->addWidget(&list);
splitter->addWidget(&table);
splitter->setWindowTitle(QObject::tr("Model/View"));
splitter->show();
//MainWindow w;
//w.show();
return a.exec();
}
- 執行結果
模型(Model)
通過實現將數值代碼轉換爲文字的模型來介紹使用自定義模型。此模型中保存了不同軍中的各種武器。
在model中會用到以下item主要的角色:
常量 | 描述 |
---|---|
Qt::DisplayRole | 顯示文字 |
Qt::DecorationRole | 繪製裝飾數據(通常是圖標) |
Qt::EditRole | 在編輯器中編輯的數據 |
Qt::ToolTipRole | 工具提示 |
Qt::StatusTipRole | 狀態欄提示 |
Qt::WhatsThisRole | What’s This文字 |
Qt::SizeHintRole | 尺寸提示 |
Qt::FontRole | 默認代理的繪製使用的字體 |
Qt::TextAlignmentRole | 默認代理的對齊方式 |
Qt::BackgroundRole | 默認代理的背景畫刷 |
Qt::ForegroundRole | 默認代理的前景畫刷 |
Qt::CheckStateRole | 默認代理的檢查框狀態 |
Qt::UserRole | 用戶自定義的數據的起始位置 |
自定義模型【示例】
-
項目結構
-
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include "modelex.h"
#include <QTableView>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ModelEx modelEx;
QTableView view;
view.setModel(&modelEx);
view.setWindowTitle(QObject::tr("modelEx"));
view.resize(400,400);
view.show();
//MainWindow w;
//w.show();
return a.exec();
}
- modelex.h
#ifndef MODELEX_H
#define MODELEX_H
#include <QAbstractTableModel>
#include <QVector>
#include <QMap>
#include <QStringList>
class ModelEx : public QAbstractTableModel
{
public:
explicit ModelEx(QObject *parent=0);
//虛函數聲明 //(a)
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const;
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
signals:
public slots:
private:
QVector<short> army;
QVector<short> weaponType;
QMap<short,QString> armyMap; //使用QMap數據結構保存“數值—文字”的映射
QMap<short,QString> weaponTypeMap;
QStringList weapon;
QStringList header;
void populateModel(); //完成表格數據的初始化填充
};
#endif // MODELEX_H
- modelex.cpp
#include "modelex.h"
ModelEx::ModelEx(QObject *parent):QAbstractTableModel(parent)
{
armyMap[1]=tr("空軍");
armyMap[2]=tr("海軍");
armyMap[3]=tr("陸軍");
armyMap[4]=tr("海軍陸戰隊");
weaponTypeMap[1]=tr("轟炸機");
weaponTypeMap[2]=tr("戰鬥機");
weaponTypeMap[3]=tr("航空母艦");
weaponTypeMap[4]=tr("驅逐艦");
weaponTypeMap[5]=tr("直升機");
weaponTypeMap[6]=tr("坦克");
weaponTypeMap[7]=tr("兩棲攻擊艦");
weaponTypeMap[8]=tr("兩棲戰車");
populateModel();
}
void ModelEx::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");
}
int ModelEx::columnCount(const QModelIndex &parent) const
{ return 3; }
int ModelEx::rowCount(const QModelIndex &parent) const
{
return army.size();
}
QVariant ModelEx::data(const QModelIndex &index, int role) const
{
if(!index.isValid())
return QVariant();
if(role==Qt::DisplayRole) //(a)
{
switch(index.column())
{
case 0:
return armyMap[army[index.row()]];
break;
case 1:
return weaponTypeMap[weaponType[index.row()]];
break;
case 2:
return weapon[index.row()];
default:
return QVariant();
}
}
return QVariant();
}
QVariant ModelEx::headerData(int section, Qt::Orientation orientation, int role) const
{
if(role==Qt::DisplayRole&&orientation==Qt::Horizontal)
return header[section];
return QAbstractTableModel::headerData(section,orientation,role);
}
- 執行結果
視圖(View)
通過自定義的view實現一個對TableModel的表格數據進行顯示的柱狀圖統計圖示例。
表格數據顯示【示例】
-
項目結構
-
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
- mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStandardItemModel>
#include <QTableView>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QSplitter>
#include "histogramview.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
void createAction();
void createMenu();
void setupModel();
void setupView();
void openFile(QString);
public slots:
void slotOpen();
private:
QMenu *fileMenu;
QAction *openAct;
QStandardItemModel *model;
QTableView *table;
QSplitter *splitter;
HistogramView *histogram;
};
#endif // MAINWINDOW_H
- mainwindow.cpp
#include "mainwindow.h"
#include <QItemSelectionModel>
#include <QFileDialog>
#include <QFile>
#include <QTextStream>
#include <QStringList>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
createAction();
createMenu();
setupModel();
setupView();
setWindowTitle(tr("View Example"));
resize(600,600);
}
MainWindow::~MainWindow()
{
}
void MainWindow::createAction()
{
openAct = new QAction(tr("打開"),this);
connect(openAct,SIGNAL(triggered()),this,SLOT(slotOpen()));
}
void MainWindow::createMenu()
{
fileMenu = new QMenu(tr("文件"),this);
fileMenu->addAction(openAct);
menuBar()->addMenu(fileMenu);
}
void MainWindow::setupModel()
{
model = new QStandardItemModel(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("退休"));
}
void MainWindow::setupView()
{
/*
table = new QTableView; //新建一個QTableView對象
table->setModel(model); //爲QTableView對象設置相同的Model
QItemSelectionModel *selectionModel=new QItemSelectionModel(model);
//(a)
table->setSelectionModel(selectionModel);
connect(selectionModel,SIGNAL(selectionChanged(QItemSelection, ItemSelection)),table,SLOT(selectionChanged(QItemSelection,QItemSelection))); //(b)
splitter = new QSplitter;
splitter->setOrientation(Qt::Vertical);
splitter->addWidget(table);
setCentralWidget(splitter);
*/
splitter = new QSplitter;
splitter->setOrientation(Qt::Vertical);
histogram = new HistogramView(splitter); //新建一個HistogramView對象
histogram->setModel(model); //爲HistogramView對象設置相同的Model
table = new QTableView;
table->setModel(model);
QItemSelectionModel *selectionModel=new QItemSelectionModel (model);
table->setSelectionModel(selectionModel);
histogram->setSelectionModel(selectionModel); //(a)
splitter->addWidget(table);
splitter->addWidget(histogram);
setCentralWidget(splitter);
connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),table,SLOT(selectionChanged(QItemSelection,QItemSelection)));
connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),histogram,SLOT(selectionChanged(QItemSelection,QItemSelection))); //(b)
}
void MainWindow::slotOpen()
{
QString name;
name = QFileDialog::getOpenFileName(this,"打開",".","histogram files (*.txt)");
if (!name.isEmpty())
openFile(name);
}
void MainWindow::openFile(QString path)
{
if (!path.isEmpty())
{
QFile file(path);
if (file.open(QFile::ReadOnly | QFile::Text))
{
QTextStream stream(&file);
QString line;
model->removeRows(0,model->rowCount(QModelIndex()),
QModelIndex());
int row = 0;
do
{
line = stream.readLine();
if (!line.isEmpty())
{
model->insertRows(row, 1, QModelIndex());
QStringList pieces = line.split(",", QString
::SkipEmptyParts);
model->setData(model->index(row, 0, QModelIndex()),
pieces.value(0));
model->setData(model->index(row, 1, QModelIndex()),
pieces.value(1));
model->setData(model->index(row, 2, QModelIndex()),
pieces.value(2));
model->setData(model->index(row,3, QModelIndex()),
pieces.value(3));
row++;
}
} while (!line.isEmpty());
file.close();
}
}
}
- histogramview.h
#ifndef HISTOGRAMVIEW_H
#define HISTOGRAMVIEW_H
#include <QAbstractItemView>
#include <QItemSelectionModel>
#include <QRegion>
#include <QMouseEvent>
class HistogramView : public QAbstractItemView
{
Q_OBJECT
public:
HistogramView(QWidget *parent=0);
//虛函數聲明
QRect visualRect(const QModelIndex &index)const;
void scrollTo(const QModelIndex &index,ScrollHint hint= EnsureVisible);
QModelIndex indexAt(const QPoint &point)const;
//爲selections賦初值
void setSelectionModel(QItemSelectionModel *selectionModel);
QRegion itemRegion(QModelIndex index);
void paintEvent(QPaintEvent *);
void mousePressEvent(QMouseEvent *event);
protected slots:
void selectionChanged(const QItemSelection &selected,
const QItemSelection &deselected);
void dataChanged(const QModelIndex &topLeft,
const QModelIndex &bottomRight);
protected:
//虛函數聲明
QModelIndex moveCursor(QAbstractItemView::CursorAction cursorAction,
Qt::KeyboardModifiers modifiers);
int horizontalOffset()const;
int verticalOffset()const;
bool isIndexHidden(const QModelIndex &index)const;
void setSelection(const QRect &rect,QItemSelectionModel:: SelectionFlags flags);//(f)
QRegion visualRegionForSelection(const QItemSelection &selection) const;
private:
QItemSelectionModel *selections; //(g)
QList<QRegion> MRegionList; //(h)
QList<QRegion> FRegionList;
QList<QRegion> SRegionList;
};
#endif // HISTOGRAMVIEW_H
- histogramview.cpp
#include "histogramview.h"
#include <QPainter>
HistogramView::HistogramView(QWidget *parent):QAbstractItemView(parent)
{
}
// paintEvent()函數具體完成柱狀統計圖繪製的工作
void HistogramView::paintEvent(QPaintEvent *)
{
QPainter painter(viewport()); //(a)
painter.setPen(Qt::black);
int x0=40;
int y0=250;
/* 完成了x、y座標軸的繪製,並標註座標軸的變量 */
//y座標軸
painter.drawLine(x0,y0,40,30);
painter.drawLine(38,32,40,30);
painter.drawLine(40,30,42,32);
painter.drawText(20,30,tr("人數"));
for(int i=1;i<5;i++)
{
painter.drawLine(-1,-i*50,1,-i*50);
painter.drawText(-20,-i*50,tr("%1").arg(i*5));
}
//x 座標軸
painter.drawLine(x0,y0,540,250);
painter.drawLine(538,248,540,250);
painter.drawLine(540,250,538,252);
painter.drawText(545,250,tr("部門"));
int posD=x0+20;
int row;
for(row=0;row<model()->rowCount(rootIndex());row++)
{
QModelIndex index=model()->index(row,0,rootIndex());
QString dep=model()->data(index).toString();
painter.drawText(posD,y0+20,dep);
posD+=50;
}
/* 完成了表格第1列數據的柱狀統計圖的繪製 */
//男
int posM=x0+20;
MRegionList.clear();
for(row=0;row<model()->rowCount(rootIndex());row++)
{
QModelIndex index=model()->index(row,1,rootIndex());
int male=model()->data(index).toDouble();
int width=10;
if(selections->isSelected(index)) //(b)
painter.setBrush(QBrush(Qt::blue,Qt::Dense3Pattern));
else
painter.setBrush(Qt::blue);
painter.drawRect(QRect(posM,y0-male*10,width,male*10));//(c)
QRegion regionM(posM,y0-male*10,width,male*10);
MRegionList.insert(row,regionM); //(d)
posM+=50;
}
/* 完成了表格第2列數據的柱狀統計圖的繪製 */ //(e)
//女
int posF=x0+30;
FRegionList.clear();
for(row=0;row<model()->rowCount(rootIndex());row++)
{
QModelIndex index=model()->index(row,2,rootIndex());
int female=model()->data(index).toDouble();
int width=10;
if(selections->isSelected(index))
painter.setBrush(QBrush(Qt::red,Qt::Dense3Pattern));
else
painter.setBrush(Qt::red);
painter.drawRect(QRect(posF,y0-female*10,width,female*10));
QRegion regionF(posF,y0-female*10,width,female*10);
FRegionList.insert(row,regionF);
posF+=50;
}
/* 完成了表格第3列數據的柱狀統計圖的繪製 */ //(f)
//退休
int posS=x0+40;
SRegionList.clear();
for(row=0;row<model()->rowCount(rootIndex());row++)
{
QModelIndex index=model()->index(row,3,rootIndex());
int retire=model()->data(index).toDouble();
int width=10;
if(selections->isSelected(index))
painter.setBrush(QBrush(Qt::green,Qt::Dense3Pattern));
else
painter.setBrush(Qt::green);
painter.drawRect(QRect(posS,y0-retire*10,width,retire*10));
QRegion regionS(posS,y0-retire*10,width,retire*10);
SRegionList.insert(row,regionS);
posS+=50;
}
}
void HistogramView::dataChanged(const QModelIndex &topLeft,
const QModelIndex &bottomRight)
{
QAbstractItemView::dataChanged(topLeft,bottomRight);
viewport()->update();
}
void HistogramView::setSelectionModel(QItemSelectionModel *selectionModel)
{
selections=selectionModel;
}
void HistogramView::selectionChanged(const QItemSelection &selected,
const QItemSelection &deselected)
{
viewport()->update();
}
void HistogramView::mousePressEvent(QMouseEvent *event)
{
QAbstractItemView::mousePressEvent(event);
setSelection(QRect(event->pos().x(),event->pos().y(),1,1),QItemSelectionModel::SelectCurrent);
}
void HistogramView::setSelection(const QRect &rect,QItemSelectionModel::SelectionFlags flags)
{
int rows = model()->rowCount(rootIndex()); //獲取總行數
int columns = model()->columnCount(rootIndex()); //獲取總列數
QModelIndex selectedIndex;
for (int row=0; row<rows; ++row)
{
for (int column=1; column<columns; ++column)
{
QModelIndex index=model()->index(row,column,rootIndex());
QRegion region=itemRegion(index);
if (!region.intersected(rect).isEmpty())
selectedIndex = index;
}
}
if(selectedIndex.isValid())
selections->select(selectedIndex,flags);
else
{
QModelIndex noIndex;
selections->select(noIndex,flags);
}
}
QModelIndex HistogramView::indexAt(const QPoint &point)const
{
QPoint newPoint(point.x(),point.y());
QRegion region;
// 男 列
foreach(region,MRegionList)
{
if (region.contains(newPoint))
{
int row = MRegionList.indexOf(region);
QModelIndex index = model()->index(row,1,rootIndex());
return index;
}
}
// 女 列
foreach(region,FRegionList)
{
if (region.contains(newPoint))
{
int row = FRegionList.indexOf(region);
QModelIndex index = model()->index(row,2,rootIndex());
return index;
}
}
// 合計 列
foreach(region,SRegionList)
{
if (region.contains(newPoint))
{
int row = SRegionList.indexOf(region);
QModelIndex index = model()->index(row,3,rootIndex());
return index;
}
}
return QModelIndex();
}
QRect HistogramView::visualRect(const QModelIndex &index)const{}
void HistogramView::scrollTo(const QModelIndex &index,ScrollHint){}
QModelIndex HistogramView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers){}
int HistogramView::horizontalOffset()const{}
int HistogramView::verticalOffset()const{}
bool HistogramView::isIndexHidden(const QModelIndex &index)const{}
QRegion HistogramView::visualRegionForSelection(const QItemSelection & selection)const{}
QRegion HistogramView::itemRegion(QModelIndex index)
{
QRegion region;
if (index.column() == 1) //男
region = MRegionList[index.row()];
if (index.column() == 2) //女
region = FRegionList[index.row()];
if (index.column() == 3) //退休
region = SRegionList[index.row()];
return region;
}
- 執行結果
代理(Delegate)
利用Delegate設計表格控件。
利用Delegate設計表格控件【示例】
- 項目結構
- main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QStandardItemModel>
#include <QTableView>
#include <QFile>
#include <QTextStream>
#include "datedelegate.h"
#include "combodelegate.h"
#include "spindelegate.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QStandardItemModel model(4,4);
QTableView tableView;
tableView.setModel(&model);
DateDelegate dateDelegate;
tableView.setItemDelegateForColumn(1,&dateDelegate);
ComboDelegate comboDelegate;
tableView.setItemDelegateForColumn(2,&comboDelegate);
SpinDelegate spinDelegate;
tableView.setItemDelegateForColumn(3,&spinDelegate);
model.setHeaderData(0,Qt::Horizontal,QObject::tr("姓名"));
model.setHeaderData(1,Qt::Horizontal,QObject::tr("生日"));
model.setHeaderData(2,Qt::Horizontal,QObject::tr("職業"));
model.setHeaderData(3,Qt::Horizontal,QObject::tr("收入"));
QFile file("test.txt");
if(file.open(QFile::ReadOnly|QFile::Text))
{
QTextStream stream(&file);
QString line;
model.removeRows(0,model.rowCount(QModelIndex()),QModelIndex());
int row =0;
do{
line = stream.readLine();
if(!line.isEmpty())
{
model.insertRows(row,1,QModelIndex());
QStringList pieces = line.split(",",QString::SkipEmptyParts);
model.setData(model.index(row,0,QModelIndex()), pieces
.value(0));
model.setData(model.index(row,1,QModelIndex()), pieces
.value(1));
model.setData(model.index(row,2,QModelIndex()), pieces
.value(2));
model.setData(model.index(row,3,QModelIndex()), pieces
.value(3));
row++;
}
}while(!line.isEmpty());
file.close();
}
tableView.setWindowTitle(QObject::tr("Delegate"));
tableView.show();
//MainWindow w;
//w.show();
return a.exec();
}
- spindelegate.h
#ifndef SPINDELEGATE_H
#define SPINDELEGATE_H
#include <QItemDelegate>
class SpinDelegate : public QItemDelegate
{
Q_OBJECT
public:
SpinDelegate(QObject *parent = 0);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
#endif // SPINDELEGATE_H
- spindelegate.cpp
#include "spindelegate.h"
#include <QSpinBox>
SpinDelegate::SpinDelegate(QObject *parent):QItemDelegate(parent)
{
}
QWidget *SpinDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
QSpinBox *editor = new QSpinBox(parent);
editor->setRange(0,10000);
editor->installEventFilter(const_cast<SpinDelegate*>(this));
return editor;
}
void SpinDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
int value =index.model()->data(index).toInt();
QSpinBox *box = static_cast<QSpinBox*>(editor);
box->setValue(value);
}
void SpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const
{
QSpinBox *box = static_cast<QSpinBox*>(editor);
int value = box->value();
model->setData(index,value);
}
void SpinDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
editor->setGeometry(option.rect);
}
- datedelegate.h
#ifndef DATEDELEGATE_H
#define DATEDELEGATE_H
#include <QItemDelegate>
class DateDelegate : public QItemDelegate
{
Q_OBJECT
public:
DateDelegate(QObject *parent = 0);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem & option, const QModelIndex &index) const; //(a)
void setEditorData(QWidget *editor, const QModelIndex &index) const; //(b)
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; //將Delegate中對數據的改變更新至Model中
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem & option, const QModelIndex &index) const; //更新控件區的顯示
};
#endif // DATEDELEGATE_H
- datedelegate.cpp
#include "datedelegate.h"
#include <QDateTimeEdit>
DateDelegate::DateDelegate(QObject *parent):QItemDelegate(parent)
{
}
QWidget *DateDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
QDateTimeEdit *editor = new QDateTimeEdit(parent); //(a)
editor->setDisplayFormat("yyyy-MM-dd"); //(b)
editor->setCalendarPopup(true); //(c)
editor->installEventFilter(const_cast<DateDelegate*>(this));
//(d)
return editor;
}
void DateDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
QString dateStr= index.model()->data(index).toString(); //(a)
QDate date = QDate::fromString(dateStr,Qt::ISODate); //(b)
QDateTimeEdit *edit=static_cast<QDateTimeEdit*>(editor); //(c)
edit->setDate(date); //設置控件的顯示數據
}
void DateDelegate::setModelData(QWidget *editor,QAbstractItemModel *model, const QModelIndex &index) const
{
QDateTimeEdit *edit=static_cast<QDateTimeEdit*>(editor);//(a)
QDate date = edit->date(); //(b)
model->setData(index,QVariant(date.toString(Qt::ISODate)));//(c)
}
void DateDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}
- combodelegate.h
#ifndef COMBODELEGATE_H
#define COMBODELEGATE_H
#include <QItemDelegate>
class ComboDelegate : public QItemDelegate
{
Q_OBJECT
public:
ComboDelegate(QObject *parent = 0);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
#endif // COMBODELEGATE_H
- combodelegate.cpp
#include "combodelegate.h"
#include <QComboBox>
ComboDelegate::ComboDelegate(QObject *parent):QItemDelegate(parent)
{
}
QWidget *ComboDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
QComboBox *editor = new QComboBox(parent);
editor->addItem("工人");
editor->addItem("農民");
editor->addItem("醫生");
editor->addItem("律師");
editor->addItem("軍人");
editor->installEventFilter(const_cast<ComboDelegate*>(this));
return editor;
}
void ComboDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
QString str =index.model()->data(index).toString();
QComboBox *box = static_cast<QComboBox*>(editor);
int i=box->findText(str);
box->setCurrentIndex(i);
}
void ComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QComboBox *box = static_cast<QComboBox*>(editor);
QString str = box->currentText();
model->setData(index,str);
}
void ComboDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
editor->setGeometry(option.rect);
}
- 執行結果