38.Qt模型/视图结构
- 1.模型/视图类
- 2.模型
- 3.视图
- 4.代理
1 模型/视图类
InterView框架提供了一些可以直接使用的模型类和视图类,如QStandardModel类,QDirModel类,QStringListModel类,以及QColumnView类,QHeaderView类,QListView类,QTableView类和QTreeView类
简单目录浏览器:
#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);
// MainWindow w
// w.show(); //新建一个QDirModel对象,为数据访问做准备,QDirModel的创建还可以设置过滤器
//即只有符合条件的文件或目录才可被访问
//QDirModel类继承自QAbstractItemModel类,为访问本地系统提供数据模型,它提供了如
//新建,删除,创建目录等一系列与文件操作相关的函数
QDirModel model; //新建三种不同的View对象,以便文件目录可以以三种不同的方式显示
QTreeView tree;
QListView list;
QTableView table; //设置View对象的Model为QDirModel对象的model
tree.setModel(&model);
list.setModel(&model);
table.setModel(&model); //设置QTreeView对象的选择方式为多选
//QAbstractItemView提供了五种选择模式,QAbstractItem View::SingleSelection.
//QAbstractItemView::NoSelection,QAbstractItemView::ContiguousSelection
//QAbstractItemView::ExtendedSelection和QAbstractItemView::MultiSelection
tree.setSelectionMode(QAbstractItemView::MultiSelection);
//设置QTableView对象与QTreeView对象使用相同的选择模型
list.setSelectionModel(tree.selectionModel());
table.setSelectionMode(tree.selectionMode()); //为了实现双击QTreeView对象中的某个目录时,QListView对象和QTableView对象显示此选定目录
//下的所有文件和目录,需要连接QTreeView对象的doubleClicked()信号与QListView对象的
//setRootIndex()槽函数
QObject::connect(&tree,SIGNAL(doubleClicked(QModelIndex)),&list,
SLOT(setRootIndex(QModelIndex)));
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(); return a.exec();
}
2 模型
实现自定义模型可以通过QAbstractItemModel类继承,也可以通过QAbstractListModel和QAbstractTableModel类继承实现列表模型或表格模型;
代码示例:
- modelx.h
#ifndef MODELEX_H
#define MODELEX_H #include <QAbstractTableModel>
#include <QVector>
#include <QMap>
#include <QStringList>
#include <QObject> class modelex:public QAbstractTableModel
{
public:
explicit modelex(QObject *parent=); 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; private:
QVector<short> army;
QVector<short> weaponType; //数值-文字映射
QMap<short,QString> armyMap;
QMap<short,QString> weaponTypeMap; QStringList weapon;
QStringList header; //完成表格数据的初始化填充
void populateModel();
}; #endif // MODELEX_H - modelx.cpp
#include "modelex.h"
#include "modelex.h"
modelex::modelex(QObject *parent):
QAbstractTableModel(parent)
{
//创建映射
armyMap[]=tr("空军");
armyMap[]=tr("海军");
armyMap[]=tr("陆军");
armyMap[]=tr("海军陆战队"); weaponTypeMap[]=tr("轰炸机");
weaponTypeMap[]=tr("战斗机");
weaponTypeMap[]=tr("航空母舰");
weaponTypeMap[]=tr("驱逐舰");
weaponTypeMap[]=tr("直升机");
weaponTypeMap[]=tr("坦克");
weaponTypeMap[]=tr("两栖攻击舰");
weaponTypeMap[]=tr("两栖战车"); //绘制模型
populateModel();
} //获取模型的行数
int modelex::rowCount(const QModelIndex &parent) const
{
return army.size();
} //返回模型的列数
int modelex::columnCount(const QModelIndex &parent) const
{
return ;
} //返回指定索引的数据,即将数值映射为文字
//循环把模型的每行每列给绘制了(函数名不能换成其他名字)
QVariant modelex::data(const QModelIndex &index, int role) const
{
if(!index.isValid())
{
return QVariant();
} //模型中的条目可以有不同个角色,这样就可以在不同的情况下提供不同的数据.
//如,Qt::DisplayRole用来存取视图中显示的文字,角色由枚举类Qt::ItemDataRole定义
//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 用户自定义的数据的起始位置
if(role==Qt::DisplayRole)
{
//遍历没一列
switch(index.column())
{
case :
//当前行数对应的军队
return armyMap[army[index.row()]];
break;
case :
//当前行数对应的类型,以及此类型对应的武器种类
return weaponTypeMap[weaponType[index.row()]];
case :
//当前行数对应的武器
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);
} //绘制
void modelex::populateModel()
{
//表头
header<<tr("军种")<<tr("武器种类")<<tr("武器")<<tr("测试");
//军队
army<<<<<<<<<<<<<<<<;
//武器种类
weaponType<<<<<<<<<<<<<<<<;
//武器
weapon<<tr("B-2")<<tr("尼米兹级")<<tr("黄蜂级")<<tr("阿利伯克级")
<<tr("阿帕奇")<<tr("AAAV")<<tr("M1A1")<<tr("F-22");
} - main.cpp
#include <QApplication> #include "modelex.h"
#include <QTableView> int main(int argc, char *argv[])
{
QApplication a(argc, argv); modelex modleEx;
QTableView view;
view.setModel(&modleEx);
view.setWindowTitle(QObject::tr("模型示例"));
view.resize(,);
view.show();
return a.exec();
}
3 视图
实现自定义的View,可继承自QAbstractItemView类,对所需的纯虚函数进行重定义与实现,对于QAbstractItemView类中的纯虚函数,在子类必须进行重定义,但不一定要实现,可根据需要选择实现.
- histogramview.h
#ifndef HISTOGRAMVIEW_H
#define HISTOGRAMVIEW_H
#include <QAbstractItemView>
#include <QItemSelectionModel>
#include <QRegion>
#include <QMouseEvent> class HistogramView : public QAbstractItemView
{
public:
HistogramView(QWidget *parent); //14-17 一定要声明
QRect visualRect(const QModelIndex &index) const;
void scrollTo(const QModelIndex &index, ScrollHint hint=EnsureVisible);
//当鼠标处在某个数据项的区域中,则返回此数据项的Index值,否则返回一个空的Index
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:
//39-48 一定要声明
QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers);
int horizontalOffset() const;
int verticalOffset() const;
bool isIndexHidden(const QModelIndex &index) const;
//将位于QRect内的数据项按照SelectionFlags(描述被选择的数据项以何种方式进行更新)
//指定的方式进行更新.QItemSelectionModel类提供多种可用的SelectionFlags,常用的有
//QItemSelectionModel::Select,QItemSelectionModel::Current等
void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags);
QRegion visualRegionForSelection(const QItemSelection &selection) const; private:
//用于保存与视图选项相关的内容
QItemSelectionModel *selections;
//用于保存其中某一类型柱状图区域范围,而每个区域是QList中的一个值
QList<QRegion> MRegionList;
QList<QRegion> FRegionList;
QList<QRegion> SRegionList; }; #endif // HISTOGRAMVIEW_H - histogramview.cpp
#include "histogramview.h" #include <QPainter> //当鼠标处在某个数据项的区域中,则返回此数据项的Index值,否则返回一个空的Index
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,,rootIndex());
return index;
}
} //检查当前点是否处于第二列(女)数据的区域中
foreach(region,FRegionList)//女列
{
if(region.contains(newPoint))
{
int row = FRegionList.indexOf(region);
QModelIndex index = model()->index(row,,rootIndex());
return index;
}
} //检查当前点是否处于第三列(合计)数据的区域中
foreach(region,SRegionList) //合计 列
{
if(region.contains(newPoint))
{
int row=SRegionList.indexOf(region);
QModelIndex index = model()->index(row,,rootIndex());
return index;
}
}
return QModelIndex();
} //为selections赋初值
void HistogramView::setSelectionModel(QItemSelectionModel *selectionModel)
{
selections=selectionModel;
} QRegion HistogramView::itemRegion(QModelIndex index)
{
QRegion region;
if(index.column()==) //男
region = MRegionList[index.row()];
if(index.column()==) //女
region = FRegionList[index.row()];
if(index.column()==) //退休
region = SRegionList[index.row()]; return region;
} //完成柱状统计图的绘制
void HistogramView::paintEvent(QPaintEvent *)
{
//以viewport()作为绘图设备新建一个QPainter对象
QPainter painter(viewport());
painter.setPen(Qt::black); int x0=;
int y0=; //20-46行完成了x,y坐标轴的绘制,并标注坐标轴的变量
//y坐标轴
painter.drawLine(x0,y0,,);
//箭头绘制
painter.drawLine(,,,);
painter.drawLine(,,,); painter.drawText(,,tr("人数"));
//绘制坐标
for(int i=;i<;i++)
{
painter.drawLine(,i*,,i*);
painter.drawText(,i*,tr("%1").arg((-i)*));
}
//x坐标轴
painter.drawLine(x0,y0,,);
painter.drawLine(,,,);
painter.drawLine(,,,);
painter.drawText(,,tr("部门")); int posD=x0+;
int row;
//遍历模式的行数
for(row=;row<model()->rowCount(rootIndex());row++)
{
//获得第0列
QModelIndex index = model()->index(row,,rootIndex());
QString dep=model()->data(index).toString(); painter.drawText(posD,y0+,dep);
posD += ;
} //50-75 完成第一列数据的柱状统计图的绘制
//男
int posM=x0+;
for(row=;row<model()->rowCount(rootIndex());row++)
{
//获得第一列
QModelIndex index=model()->index(row,,rootIndex());
int male = model()->data(index).toDouble(); int width = ;
//使用不同画刷颜色区别选择与未被选择的数据项
if(selections->isSelected(index))
{
painter.setBrush(QBrush(Qt::blue,Qt::Dense3Pattern));
}
else
{
painter.setBrush(Qt::blue);
} //根据当前数据项的值按比例绘制一个方形表示此数据项
painter.drawRect(QRect(posM,y0-male*,width,male*));
QRegion regionM(posM,y0-male*,width,male*);
//将此数据所占据的区域保存到MRegionList列表中,为后面的数据项选择做准备
MRegionList<<regionM;
posM+=;
} //77-100 完成表格第二列数据的柱状统计图的绘制,同样,使用不同的画刷颜色区别
//选中与未被选中的数据项,同时保存每个数据所占的区域至FRegionList列表中.
//女
int posF=x0+;
for(row=;row<model()->rowCount(rootIndex());row++)
{
QModelIndex index=model()->index(row,,rootIndex());
int female = model()->data(index).toDouble(); int width = ;
if(selections->isSelected(index))
{
painter.setBrush(QBrush(Qt::red,Qt::Dense3Pattern));
}
else
{
painter.setBrush(Qt::red);
} //左上角坐标,宽,长度
painter.drawRect(QRect(posF,y0-female*,width,female*));
//把区域添加到FRegionList
QRegion regionM(posF,y0-female*,width,female*);
FRegionList<<regionM;
posF+=;
} //102-125 完成表格第三列数据的柱状统计图的绘制,同样,使用不同的画刷颜色区别
//选中与未被选中的数据项,同时保存每个数据所占的区域至FRegionList列表中.
//退休
int posS=x0+;
for(row=;row<model()->rowCount(rootIndex());row++)
{
QModelIndex index=model()->index(row,,rootIndex());
int retire = model()->data(index).toDouble(); int width = ;
if(selections->isSelected(index))
{
painter.setBrush(QBrush(Qt::green,Qt::Dense3Pattern));
}
else
{
painter.setBrush(Qt::green);
} painter.drawRect(QRect(posS,y0-retire*,width,retire*));
QRegion regionS(posS,y0-retire*,width,retire*);
SRegionList<<regionS;
posS+=;
}
} //柱状统计图可以被鼠标单击选择,选中后以不同的方式显示
//在调用setSelection()函数时确定鼠标单击点是否在某个数据项的区域内,并设置选择项
void HistogramView::mousePressEvent(QMouseEvent *event)
{
QAbstractItemView::mousePressEvent(event);
setSelection(QRect(event->pos().x(),event->pos().y(),,),
QItemSelectionModel::SelectCurrent);
} //当数据项变化时调用update()函数,重绘绘图设备,此函数是将其他View中的操作引起的数据项选择变化反映到自身View的显示中
void HistogramView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
viewport()->update();
} //当model中的数据更改时,调用绘图设备的update()函数进行更新,反映数据段的变化
void HistogramView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
QAbstractItemView::dataChanged(topLeft,bottomRight);
viewport()->update();
} //将位于QRect内的数据项按照SelectionFlags(描述被选择的数据项以何种方式进行更新)
//指定的方式进行更新.QItemSelectionModel类提供多种可用的SelectionFlags,常用的有
//QItemSelectionModel::Select,QItemSelectionModel::Current等
void HistogramView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags)
{
//获取总行数
int rows = model()->rowCount(rootIndex());
//获取总列数
int columns = model()->columnCount(rootIndex());
//用于保存被选中的数据项的Index值.此处只实现鼠标单击选择,而
//没有实现鼠标拖拽框选,因此,鼠标动作只可能选中一个数据项.
//若实现框选,则可使用QModelIndexList来保存所有被选中的数据项的Index值
QModelIndex selectedIndex; //确定在rect中是否含有数据项.此处采用遍历的方式将每个数据项的区域与rect区域进行intersected操作
//获得两者之间的交集.若此交集不为空则说明此数据项被选中,将它的Index赋值给selectedIndex
for(int row=;row<rows;++row)
{
for(int column=;column<columns;++column)
{
QModelIndex index=model()->index(row,column,rootIndex());
QRegion region = itemRegion(index); if(!region.intersected(rect).isEmpty())
{
selectedIndex = index;
}
}
if(selectedIndex.isValid())
{
//select()函数时在实现setSelection()函数时必须调用的
selections->select(selectedIndex,flags);
}
else
{
QModelIndex noIndex;
selections->select(noIndex,flags);
}
}
} 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
{ } HistogramView::HistogramView(QWidget *parent)
:QAbstractItemView(parent)
{ } QRect HistogramView::visualRect(const QModelIndex &index) const
{ } void HistogramView::scrollTo(const QModelIndex &index, QAbstractItemView::ScrollHint hint)
{ } - 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" namespace Ui {
class MainWindow;
} class MainWindow : public QMainWindow
{
Q_OBJECT public:
explicit MainWindow(QWidget *parent = );
~MainWindow();
void createAction();
void createMenu();
void setupModel();
void setupView(); public:
void openFile(QString); public slots:
void slotOpen(); private:
Ui::MainWindow *ui; QMenu *fileMenu;
QAction *openAct; QStandardItemModel *model;
QTableView *table;
QSplitter *splitter; private:
HistogramView *histogram;
}; #endif // MAINWINDOW_H - mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h" #include <QFileDialog>
#include <QFile>
#include <QTextStream>
#include <QStringList> MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建菜单项
createAction();
//创建菜单
createMenu();
//创建模型
setupModel();
//创建视图
setupView(); setWindowTitle(tr("View Example"));
resize(,); } MainWindow::~MainWindow()
{
delete ui;
} //创建菜单选项
void MainWindow::createAction()
{
openAct = new QAction(tr("打开"),this); connect(openAct,SIGNAL(triggered(bool)),this,SLOT(slotOpen()));
} //创建菜单
void MainWindow::createMenu()
{
fileMenu=new QMenu(tr("文件"),this);
fileMenu->addAction(openAct);
menuBar()->addMenu(fileMenu);
} //新建一个Model并设置表头数据
void MainWindow::setupModel()
{
//创建模型4行4列
model = new QStandardItemModel(,,this);
model->setHeaderData(,Qt::Horizontal,tr("部门"));
model->setHeaderData(,Qt::Horizontal,tr("男"));
model->setHeaderData(,Qt::Horizontal,tr("女"));
model->setHeaderData(,Qt::Horizontal,tr("退休")); } //创建视图
void MainWindow::setupView()
{
//分割窗口
splitter = new QSplitter;
splitter->setOrientation(Qt::Vertical); //新建一个HistogramView对象,在splitter中绘制
histogram = new HistogramView(splitter); //为HistogramView对象设置相同的Model
histogram->setModel(model);
//创建表格视图
table = new QTableView;
//为QTableView对象设置相同的Model
table->setModel(model); //新建一个QItemSelectionModel对象作为QTableView对象使用的选择模型
//使选择table可以在柱状图上面显示
QItemSelectionModel *selectionModel=new QItemSelectionModel(model);
table->setSelectionModel(selectionModel);
histogram->setSelectionModel(selectionModel); //添加table和histogram
splitter->addWidget(table);
splitter->addWidget(histogram); //设置中心控件
setCentralWidget(splitter); //连接选择模型的selectionChanged()信号与HistogramView对象的SelectionChanged()槽函数,以便使
//QTableView对象中的选择变化能够反映到table和自定义的HistogramView对象的显示中
connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
table,SLOT(selectionChanged(QItemSelection,QItemSelection)));
connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
histogram,SLOT(selectionChanged(QItemSelection,QItemSelection)));
} //打开文件并读取
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(,model->rowCount(QModelIndex()),
QModelIndex());
int row = ;
do
{
//依次读取每一行
line = stream.readLine();
//如果读取的不为空
if(!line.isEmpty())
{
//插入一行数据
model->insertRows(row,,QModelIndex());
//根据逗号拆分成很多部分
QStringList pieces = line.split(",",QString::SkipEmptyParts);
//分别填充第row行,0,1,2,3列
model->setData(model->index(row,,QModelIndex()),
pieces.value());
model->setData(model->index(row,,QModelIndex()),
pieces.value());
model->setData(model->index(row,,QModelIndex()),
pieces.value());
model->setData(model->index(row,,QModelIndex()),
pieces.value());
row++;
} }while(!line.isEmpty());
file.close();
}
}
} //与打开菜单项相对应的槽函数
void MainWindow::slotOpen()
{
QString name;
name = QFileDialog::getOpenFileName(this,"打开",".","histogram files(*.txt)");
if(!name.isEmpty())
{
openFile(name);
}
} - main.cpp
#include "mainwindow.h"
#include <QApplication> int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show(); return a.exec();
}
4 代理
在表格中嵌入各种不同控件,通过表格中的控件对编辑的内容进行限定.通常情况下,这种在表格中插入控件的方式,控件始终显示.当表格中控件数据较多时,将影响表格的美观.此时,可以利用Delegate的方式实现同样的效果,控件只有在需要编辑数据项的时候才会显示,从而解决了上述问题.
运行效果
- datadelegate.h
#ifndef DATADELEGATE_H
#define DATADELEGATE_H #include <QItemDelegate> class DataDelegate : public QItemDelegate
{
Q_OBJECT public:
DataDelegate(QObject *parent=);
//完成创建控件的工作,创建由参数中的QModelIndex对象指定的表项数据的编辑控件
//并对控件的内容进行限定
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
//设置控件显示的数据,将Model中的数据更新至Delegate中,相当于一个初始化工作
void setEditorData(QWidget *editor,const QModelIndex &index) const;
//将Deletate中对数据的改变更新至Model中
void setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index) const;
//更新控件区的显示
void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const;
}; #endif // DATADELEGATE_H - datadelegate.cpp
#include "datadelegate.h" #include <QDateTimeEdit> DataDelegate::DataDelegate(QObject *parent)
: QItemDelegate(parent)
{ } //完成创建控件的工作,创建由参数中的QModelIndex对象指定的表项数据的编辑控件
//并对控件的内容进行限定
QWidget *DataDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//新建一个QDataTimeEdit对象作为编辑时的输入控件
QDateTimeEdit *editor = new QDateTimeEdit(parent);
//设置此QDateTimeEdit对象的显示格式为yyyy-MM-dd,此为ISO标准显示方式
//日期的显示格式有很多种,可设定为:
//yy.MM.dd 14.01.01
//d.MM.yyyy 1.01.2014
//其中,y表示年,M表示月份(必须大写),d表示日
editor->setDisplayFormat("yyyy-MM-dd");
//设置日历选择的显示以Popup的方式,即下拉菜单方式显示
editor->setCalendarPopup(true);
//调用QObject类的installEventFilter()函数安装事件过滤器,使DataDelegate
//能够捕获QDateTimeEdit对象的事件
editor->installEventFilter(const_cast<DataDelegate *>(this));
return editor; } //设置控件显示的数据,将Model中的数据更新至Delegate中,相当于一个初始化工作
void DataDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
//获取指定index数据项的数据.调用QModelIndex的model()函数可以获得提供index的Model对象
//data()函数返回的是一个QVariant对象,toString()函数将它转换为一个QString类型数据
QString dateStr=index.model()->data(index).toString();
//通过QDate的fromString()函数将以QString类型表示的日期数据转换为QDate类型.
//Qt::ISODate表示QDate类型的日期是以ISO格式保存的,这样最终转换获得的QDate数据也是ISO格式
//使控件显示与表格显示保持一致
QDate date = QDate::fromString(dateStr,Qt::ISODate); //将editor转换为QDateTimeEdit对象,以获得编辑控件的对象指针
QDateTimeEdit *edit=static_cast<QDateTimeEdit*>(editor);
//设置控件的显示数据
edit->setDate(date);
} //将Deletate中对数据的改变更新至Model中
void DataDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
//通过紧缩转换获得编辑控件的对象指针
QDateTimeEdit *edit = static_cast<QDateTimeEdit*>(editor);
//获得编辑控件中的数据更新
QDate date = edit->date();
//调用setDat()函数将数据修改更新到Model中
model->setData(index,QVariant(date.toString(Qt::ISODate)));
} //更新控件区的显示
void DataDelegate::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=); //完成创建控件的工作,创建由参数中的QModelIndex对象指定的表项数据的编辑控件
//并对控件的内容进行限定
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
//设置控件显示的数据,将Model中的数据更新至Delegate中,相当于一个初始化工作
void setEditorData(QWidget *editor,const QModelIndex &index) const;
//将Deletate中对数据的改变更新至Model中
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)
{ } //创建一个QComboBox控件,并插入可显示的条目,安装事件过滤器
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;
} //更新Delegate控件的数据显示(双击时调用)
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);
} //setModelData()函数中更新了Model中的数据
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);
} - spindelegate.h
#ifndef SPINDELEGATE_H
#define SPINDELEGATE_H #include <QItemDelegate> class SpinDelegate : public QItemDelegate
{
public:
SpinDelegate(QObject *parent = ); //完成创建控件的工作,创建由参数中的QModelIndex对象指定的表项数据的编辑控件
//并对控件的内容进行限定
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
//设置控件显示的数据,将Model中的数据更新至Delegate中,相当于一个初始化工作
void setEditorData(QWidget *editor,const QModelIndex &index) const;
//将Deletate中对数据的改变更新至Model中
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(,);
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);
} - main.cpp
#include "mainwindow.h"
#include <QApplication> #include <QApplication>
#include <QStandardItemModel>
#include <QTableView>
#include <QFile>
#include <QTextStream> #include "datadelegate.h"
#include "combodelegate.h"
#include "spindelegate.h" int main(int argc, char *argv[])
{
QApplication a(argc, argv); QStandardItemModel model(,);
QTableView tableView;
tableView.setModel(&model); DataDelegate dateDelegate;
//第一列与dataDelegate关联
tableView.setItemDelegateForColumn(,&dateDelegate); ComboDelegate ComboDelegate;
tableView.setItemDelegateForColumn(,&ComboDelegate); SpinDelegate SpinDelegate;
tableView.setItemDelegateForColumn(,&SpinDelegate); model.setHeaderData(,Qt::Horizontal,QObject::tr("Name"));
model.setHeaderData(,Qt::Horizontal,QObject::tr("Birthday"));
model.setHeaderData(,Qt::Horizontal,QObject::tr("Job"));
model.setHeaderData(,Qt::Horizontal,QObject::tr("Income")); QFile file("test.txt");
if(file.open(QFile::ReadOnly|QFile::Text))
{
QTextStream stream(&file);
QString line; model.removeRows(,model.rowCount(QModelIndex()),QModelIndex()); int row = ;
do
{
line = stream.readLine();
if(!line.isEmpty())
{
model.insertRows(row,,QModelIndex());
QStringList pieces = line.split(",",QString::SkipEmptyParts);
model.setData(model.index(row,,QModelIndex()),pieces.value());
model.setData(model.index(row,,QModelIndex()),pieces.value());
model.setData(model.index(row,,QModelIndex()),pieces.value());
model.setData(model.index(row,,QModelIndex()),pieces.value());
row++;
}
}while(!line.isEmpty()); file.close();
} tableView.setWindowTitle(QObject::tr("Delegate"));
tableView.show(); return a.exec();
}
38.Qt模型/视图结构的更多相关文章
- Qt 模型/视图结构
MVC是一种与用户界面相关的设计模式.通过使用此模型,可以有效地分离数据和用户界面.MVC设计模式包含三要素:表示数据的模型(Model).表示用户界面的视图(View)和定义了用户在界面上的操作控制 ...
- Qt模型视图结构遇见的小问题
在本文的最开始,我们来看两个帮助文档内容: selectionMode : SelectionMode This property holds which selection mode the vie ...
- Qt模型/视图、委托
MVC视图和控制器对象相结合,其结果是模型/视图结构,仍然分离了数据与呈现给用户的方式,使得它可以在几个不同的视图中显示相同的数据,并实现新类型的视图而无需改变底层的数据结构.为了灵活的处理数据输入, ...
- Qt 模型/视图/委托
模型.视图.委托 模型/视图架构基于MVC设计模式发展而来.MVC中,模型(Model)用来表示数据:视图(View)是界面,用来显示数据:控制(Controller)定义界面对用户输入的反应方式. ...
- Qt模型/视图框架----简单的例子
#include<qapplication.h> #include<qfilesystemmodel.h> #include<qtreeview.h> #inclu ...
- Qt5模型/视图结构-视图(View)
实现自定义的View,可继承自QAbstractItemView类,对所需的纯虚函数进行重定义与实现,对于QAbstractItemView类中的纯虚函数,在子类中必须进行重定义,但不一定要实现,可根 ...
- 【转】Qt之模型/视图
[本文转自]http://blog.sina.com.cn/s/blog_a6fb6cc90101hh20.html 作者: 一去丶二三里 关于Qt中MVC的介绍与使用,助手中有一节模型/视图编程 ...
- Qt Model/View(模型/视图)结构(无师自通)
Model/View(模型/视图)结构是 Qt 中用界面组件显示与编辑数据的一种结构,视图(View)是显示和编辑数据的界面组件,模型(Model)是视图与原始数据之间的接口. GUI 应用程序的一个 ...
- Qt之模型/视图(自定义进度条)
简述 在之前的章节中分享过关于QHeaderView表头排序.添加复选框等内容,相信大家模型/视图.自定义风格有了一定的了解,下面我们来分享一个更常用的内容-自定义进度条. 实现方式: 从QAbstr ...
随机推荐
- showdialog
在C#中窗口的显示有两种方式:模态显示(showdialog)和非模态显示(show). 区别: 模态与非模态窗体的主要区别是窗体显示的时候是否可以操作其他窗体.模态窗体不允许操作其他窗体,非模态窗体 ...
- 初步学习Axure---整理了一下自己两周的学习成果:动态面板
自己无意间发现了做原型设计的工具--Axure,所以就自学了一点皮毛.最近时间比较充裕,就把自己现学现卖的东西整一整. 作品比较简单,没有技术可言,根据用户和开发需求,利用动态面板和一些点击事件完成了 ...
- phpstudy不显示目录列表---设置方法
打开phpstudy,显示的项目文件路径不见了,其实是phpstudy的设置问题.以下是设置方法. 并将一下几个文件删除即可
- (转)shiro权限框架详解06-shiro与web项目整合(下)
http://blog.csdn.net/facekbook/article/details/54962975 shiro和web项目整合,实现类似真实项目的应用 web项目中认证 web项目中授权 ...
- springboot-简介
SpringBoot是Spring项目中的一个子工程,与我们所熟知的Spring-framework 同属于spring的产品: 下载地址: Spring Boot 主要目标是: 为所有 Spring ...
- Kattis - Game Rank
Game Rank Picture by Gonkasth on DeviantArt, cc by-nd The gaming company Sandstorm is developing an ...
- 转载:html特殊字符 编码css3 content:&quot;我是特殊符号&quot;
项目中用到的一些特殊字符和图标 html代码 <div class="cross"></div> css代码 .cross{ width: 20px; he ...
- java 常用API 包装
package com.oracel.demo01; public class Baozhuang { //将字符串转成基本数据类型 public static void main(String[] ...
- BZOJ 1691 [Usaco2007 Dec]挑剔的美食家 multiset_排序_贪心
Description 与很多奶牛一样,Farmer John那群养尊处优的奶牛们对食物越来越挑剔,随便拿堆草就能打发她们午饭的日子自然是一去不返了.现在,Farmer John不得不去牧草专供商那里 ...
- 历年真题 未完成(Noip 2008 - Noip 2017)
Noip 2008 :全部 Noip 2009 :全部 Noip 2010 :AK Noip 2011 :AK Noip 2012 : Vigenère 密码,国王游戏,开车旅行 Noip 2013 ...