• 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模型/视图结构的更多相关文章

  1. Qt 模型/视图结构

    MVC是一种与用户界面相关的设计模式.通过使用此模型,可以有效地分离数据和用户界面.MVC设计模式包含三要素:表示数据的模型(Model).表示用户界面的视图(View)和定义了用户在界面上的操作控制 ...

  2. Qt模型视图结构遇见的小问题

    在本文的最开始,我们来看两个帮助文档内容: selectionMode : SelectionMode This property holds which selection mode the vie ...

  3. Qt模型/视图、委托

    MVC视图和控制器对象相结合,其结果是模型/视图结构,仍然分离了数据与呈现给用户的方式,使得它可以在几个不同的视图中显示相同的数据,并实现新类型的视图而无需改变底层的数据结构.为了灵活的处理数据输入, ...

  4. Qt 模型/视图/委托

    模型.视图.委托 模型/视图架构基于MVC设计模式发展而来.MVC中,模型(Model)用来表示数据:视图(View)是界面,用来显示数据:控制(Controller)定义界面对用户输入的反应方式. ...

  5. Qt模型/视图框架----简单的例子

    #include<qapplication.h> #include<qfilesystemmodel.h> #include<qtreeview.h> #inclu ...

  6. Qt5模型/视图结构-视图(View)

    实现自定义的View,可继承自QAbstractItemView类,对所需的纯虚函数进行重定义与实现,对于QAbstractItemView类中的纯虚函数,在子类中必须进行重定义,但不一定要实现,可根 ...

  7. 【转】Qt之模型/视图

    [本文转自]http://blog.sina.com.cn/s/blog_a6fb6cc90101hh20.html   作者: 一去丶二三里 关于Qt中MVC的介绍与使用,助手中有一节模型/视图编程 ...

  8. Qt Model/View(模型/视图)结构(无师自通)

    Model/View(模型/视图)结构是 Qt 中用界面组件显示与编辑数据的一种结构,视图(View)是显示和编辑数据的界面组件,模型(Model)是视图与原始数据之间的接口. GUI 应用程序的一个 ...

  9. Qt之模型/视图(自定义进度条)

    简述 在之前的章节中分享过关于QHeaderView表头排序.添加复选框等内容,相信大家模型/视图.自定义风格有了一定的了解,下面我们来分享一个更常用的内容-自定义进度条. 实现方式: 从QAbstr ...

随机推荐

  1. 使用Micrisoft.net设计方案 第三章Web表示模式

    第三章Web表示模式 体系结构设计者在设计第一个作品时比较精简和干练.在第一次设计时,并清除自己做什么,因此比较小心谨慎.第二个作品是最危险的一个作品,此时他会对第一个作品做修饰和润色,以及把第一次设 ...

  2. hdu1829 A Bug's Life 基础种类并查集

    题目的大意可以理解为:A爱B,B爱C ……给出一系列爱恋的关系,推断有没有同性恋. 思路是把相同性别的归为一个集合(等价类),异性的异性为同性. #include<iostream> #i ...

  3. wp7图片上传服务器

    做一个wp7手机上传图片到服务器的功能,具体丝路是在手机端做一个照相或者选择图片的功能,点击上传,在服务器端做一个一般处理程序,接受上传的文件,存入文件夹,下面是主要代码: 手机端代码: /// &l ...

  4. VS2012编译PCL1.70的过程

    以防博主删除文档,重新copy一遍... 关于个人的几个注意事项: 对于boost,可以使用vc100的库,来编译VC110的代码: 对于确实的包含,一个一个添加,要耐心等待!!! 原文链接:http ...

  5. 【从零开始】【Java】【1】Git和svn

    闲聊 干活快一年了吧,感觉工作中能干的事情也有一点了,但总有种不通透的感觉,查一个问题,能一路查出一堆不明白的东西. 之前新建过文档是记录点点滴滴的知识的,使用上没问题了,但原理什么的还是不懂,想了想 ...

  6. javase 超市库存系统

    package com.oracle.demo01; import java.util.ArrayList; import java.util.Scanner; public class Demo01 ...

  7. 在fedora「27」下,安装mysql 问题总结

    有时会出现,没有mysql.sock,不存在的问题, Can't connect to local MySQL server through socket '/var/lib/mysql/mysql. ...

  8. [IOI2011]Race $O(nlog^{2}n)$ 做法

    这个应该还不是正解,明天看一下正解到底是什么... Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in&qu ...

  9. python与图灵机器人交互(ITCHAT版本)

    #!/usr/bin/env python#-*- coding:utf-8 -*- @Author : wujf @Time:2018/9/5 17:42import requestsimport ...

  10. luogu P4756 Added Sequence(凸包+思维)

    一眼望去不会. 考虑问题中的\(f(i,j)=|\sum_{p=i}^{j}​a_p​ |\)的实际意义. 其实就是前缀和相减的绝对值. \(f(i,j)=|\ sum[j]-sum[i-1]\ |\ ...