• 38.Qt模型/视图结构


    • 1.模型/视图类
    • 2.模型
    • 3.视图
    • 4.代理

    1  模型/视图类

      InterView框架提供了一些可以直接使用的模型类和视图类,如QStandardModel类,QDirModel类,QStringListModel类,以及QColumnView类,QHeaderView类,QListView类,QTableView类和QTreeView类

    简单目录浏览器:

     1 #include "mainwindow.h"
     2 #include <QApplication>
     3 
     4 #include <QAbstractItemModel>
     5 #include <QAbstractItemView>
     6 #include <QItemSelectionModel>
     7 
     8 #include <QDirModel>
     9 #include <QTreeView>
    10 #include <QListView>
    11 #include <QTableView>
    12 #include <QSplitter>
    13 
    14 int main(int argc, char *argv[])
    15 {
    16     QApplication a(argc, argv);
    17 //    MainWindow w
    18 //    w.show();
    19 
    20     //新建一个QDirModel对象,为数据访问做准备,QDirModel的创建还可以设置过滤器
    21     //即只有符合条件的文件或目录才可被访问
    22     //QDirModel类继承自QAbstractItemModel类,为访问本地系统提供数据模型,它提供了如
    23     //新建,删除,创建目录等一系列与文件操作相关的函数
    24     QDirModel model;
    25 
    26     //新建三种不同的View对象,以便文件目录可以以三种不同的方式显示
    27     QTreeView tree;
    28     QListView list;
    29     QTableView table;
    30 
    31     //设置View对象的Model为QDirModel对象的model
    32     tree.setModel(&model);
    33     list.setModel(&model);
    34     table.setModel(&model);
    35 
    36     //设置QTreeView对象的选择方式为多选
    37     //QAbstractItemView提供了五种选择模式,QAbstractItem View::SingleSelection.
    38     //QAbstractItemView::NoSelection,QAbstractItemView::ContiguousSelection
    39     //QAbstractItemView::ExtendedSelection和QAbstractItemView::MultiSelection
    40     tree.setSelectionMode(QAbstractItemView::MultiSelection);
    41     //设置QTableView对象与QTreeView对象使用相同的选择模型
    42     list.setSelectionModel(tree.selectionModel());
    43     table.setSelectionMode(tree.selectionMode());
    44 
    45     //为了实现双击QTreeView对象中的某个目录时,QListView对象和QTableView对象显示此选定目录
    46     //下的所有文件和目录,需要连接QTreeView对象的doubleClicked()信号与QListView对象的
    47     //setRootIndex()槽函数
    48     QObject::connect(&tree,SIGNAL(doubleClicked(QModelIndex)),&list,
    49                      SLOT(setRootIndex(QModelIndex)));
    50     QObject::connect(&tree,SIGNAL(doubleClicked(QModelIndex)),&table,
    51                      SLOT(setRootIndex(QModelIndex)));
    52 
    53     QSplitter *splitter = new QSplitter;
    54     splitter->addWidget(&tree);
    55     splitter->addWidget(&list);
    56     splitter->addWidget(&table);
    57     splitter->setWindowTitle(QObject::tr("Model/view"));
    58     splitter->show();
    59 
    60     return a.exec();
    61 }

    2  模型

      实现自定义模型可以通过QAbstractItemModel类继承,也可以通过QAbstractListModel和QAbstractTableModel类继承实现列表模型或表格模型;

    代码示例:

    • modelx.h
       1 #ifndef MODELEX_H
       2 #define MODELEX_H
       3 
       4 #include <QAbstractTableModel>
       5 #include <QVector>
       6 #include <QMap>
       7 #include <QStringList>
       8 #include <QObject>
       9 
      10 class modelex:public QAbstractTableModel
      11 {
      12 public:
      13     explicit modelex(QObject *parent=0);
      14 
      15     virtual int rowCount(const QModelIndex &parent=QModelIndex()) const;
      16     virtual int columnCount(const QModelIndex &parent=QModelIndex()) const;
      17 
      18     QVariant data(const QModelIndex &index, int role) const;
      19     //返回表头的函数
      20     QVariant headerData(int section,Qt::Orientation orientation,int role)const;
      21 
      22 private:
      23     QVector<short> army;
      24     QVector<short> weaponType;
      25 
      26     //数值-文字映射
      27     QMap<short,QString> armyMap;
      28     QMap<short,QString> weaponTypeMap;
      29 
      30     QStringList weapon;
      31     QStringList header;
      32 
      33     //完成表格数据的初始化填充
      34     void populateModel();
      35 };
      36 
      37 #endif // MODELEX_H
    • modelx.cpp
        1 #include "modelex.h"
        2 #include "modelex.h"
        3 modelex::modelex(QObject *parent):
        4     QAbstractTableModel(parent)
        5 {
        6     //创建映射
        7     armyMap[1]=tr("空军");
        8     armyMap[2]=tr("海军");
        9     armyMap[3]=tr("陆军");
       10     armyMap[4]=tr("海军陆战队");
       11 
       12     weaponTypeMap[1]=tr("轰炸机");
       13     weaponTypeMap[2]=tr("战斗机");
       14     weaponTypeMap[3]=tr("航空母舰");
       15     weaponTypeMap[4]=tr("驱逐舰");
       16     weaponTypeMap[5]=tr("直升机");
       17     weaponTypeMap[6]=tr("坦克");
       18     weaponTypeMap[7]=tr("两栖攻击舰");
       19     weaponTypeMap[8]=tr("两栖战车");
       20 
       21     //绘制模型
       22     populateModel();
       23 }
       24 
       25 
       26 
       27 //获取模型的行数
       28 int modelex::rowCount(const QModelIndex &parent) const
       29 {
       30     return army.size();
       31 }
       32 
       33 //返回模型的列数
       34 int modelex::columnCount(const QModelIndex &parent) const
       35 {
       36     return 4;
       37 }
       38 
       39 //返回指定索引的数据,即将数值映射为文字
       40 //循环把模型的每行每列给绘制了(函数名不能换成其他名字)
       41 QVariant modelex::data(const QModelIndex &index, int role) const
       42 {
       43     if(!index.isValid())
       44     {
       45         return QVariant();
       46     }
       47 
       48     //模型中的条目可以有不同个角色,这样就可以在不同的情况下提供不同的数据.
       49     //如,Qt::DisplayRole用来存取视图中显示的文字,角色由枚举类Qt::ItemDataRole定义
       50     //Qt::DisplayRole   显示文字
       51     //Qt::DecorationRole   绘制装饰数据(通常是图标)
       52     //Qt::EditRole   在编辑器中编辑的数据
       53     //Qt::ToolTipRole   工具提示
       54     //Qt::StatusTipRole   状态栏提示
       55     //Qt::WhatsThisRole   What's This文字
       56     //Qt::SizeHintRole   尺寸提示
       57     //Qt::FontRole   默认代理的绘制使用的字体
       58     //Qt::TextAlignmentRole   默认代理的对齐方式
       59     //Qt::BackgroundRole   默认代理的背景画刷
       60     //Qt::ForegroundRole   默认代理的前景画刷
       61     //Qt::CheckStateRole   默认代理的检查框状态
       62     //Qt::UserRole   用户自定义的数据的起始位置
       63     if(role==Qt::DisplayRole)
       64     {
       65         //遍历没一列
       66         switch(index.column())
       67         {
       68         case 0:
       69             //当前行数对应的军队
       70             return armyMap[army[index.row()]];
       71             break;
       72         case 1:
       73             //当前行数对应的类型,以及此类型对应的武器种类
       74             return weaponTypeMap[weaponType[index.row()]];
       75         case 2:
       76             //当前行数对应的武器
       77             return weapon[  index.row()  ];
       78         default:
       79             return QVariant();
       80         }
       81     }
       82     return QVariant();
       83 }
       84 
       85 //返回固定的表头数据,设置水平表头的标题(内部循环实现)
       86 QVariant modelex::headerData(int section, Qt::Orientation orientation, int role) const
       87 {
       88     if(role==Qt::DisplayRole&&orientation==Qt::Horizontal)
       89         return header[section];
       90 
       91     return QAbstractTableModel::headerData(section,orientation,role);
       92 }
       93 
       94 //绘制
       95 void modelex::populateModel()
       96 {
       97     //表头
       98     header<<tr("军种")<<tr("武器种类")<<tr("武器")<<tr("测试");
       99     //军队
      100     army<<1<<2<<3<<4<<2<<4<<3<<1;
      101     //武器种类
      102     weaponType<<1<<3<<5<<7<<4<<8<<6<<3;
      103     //武器
      104     weapon<<tr("B-2")<<tr("尼米兹级")<<tr("黄蜂级")<<tr("阿利伯克级")
      105          <<tr("阿帕奇")<<tr("AAAV")<<tr("M1A1")<<tr("F-22");
      106 }
    • main.cpp
       1 #include <QApplication>
       2 
       3 #include "modelex.h"
       4 #include <QTableView>
       5 
       6 int main(int argc, char *argv[])
       7 {
       8     QApplication a(argc, argv);
       9 
      10     modelex modleEx;
      11     QTableView view;
      12     view.setModel(&modleEx);
      13     view.setWindowTitle(QObject::tr("模型示例"));
      14     view.resize(400,400);
      15     view.show();
      16     return a.exec();
      17 }

    3  视图

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

    • histogramview.h
       1 #ifndef HISTOGRAMVIEW_H
       2 #define HISTOGRAMVIEW_H
       3 #include <QAbstractItemView>
       4 #include <QItemSelectionModel>
       5 #include <QRegion>
       6 #include <QMouseEvent>
       7 
       8 
       9 
      10 class HistogramView : public QAbstractItemView
      11 {
      12 public:
      13     HistogramView(QWidget *parent);
      14 
      15     //14-17 一定要声明
      16     QRect visualRect(const QModelIndex &index) const;
      17     void scrollTo(const QModelIndex &index, ScrollHint hint=EnsureVisible);
      18     //当鼠标处在某个数据项的区域中,则返回此数据项的Index值,否则返回一个空的Index
      19     QModelIndex indexAt(const QPoint &point) const;
      20 
      21 
      22     //为selections赋初值
      23     void setSelectionModel(QItemSelectionModel *selectionModel);
      24     QRegion itemRegion(QModelIndex index);
      25 
      26     //完成柱状统计图的绘制
      27     void paintEvent(QPaintEvent *);
      28     //柱状统计图可以被鼠标单击选择,选中后以不同的方式显示
      29     void mousePressEvent(QMouseEvent *event);
      30 
      31 protected slots:
      32     //当数据项选择发生变化时此槽函数将响应
      33     void selectionChanged(const QItemSelection &selected,
      34                           const QItemSelection &deselected);
      35     //当模型中的数据发生变更时,此槽函数将响应
      36     void dataChanged(const QModelIndex &topLeft,
      37                      const QModelIndex &bottomRight);
      38 
      39 protected:
      40     //39-48 一定要声明
      41     QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers);
      42     int horizontalOffset() const;
      43     int verticalOffset() const;
      44     bool isIndexHidden(const QModelIndex &index) const;
      45     //将位于QRect内的数据项按照SelectionFlags(描述被选择的数据项以何种方式进行更新)
      46     //指定的方式进行更新.QItemSelectionModel类提供多种可用的SelectionFlags,常用的有
      47     //QItemSelectionModel::Select,QItemSelectionModel::Current等
      48     void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags);
      49     QRegion visualRegionForSelection(const QItemSelection &selection) const;
      50 
      51 private:
      52     //用于保存与视图选项相关的内容
      53     QItemSelectionModel *selections;
      54     //用于保存其中某一类型柱状图区域范围,而每个区域是QList中的一个值
      55     QList<QRegion> MRegionList;
      56     QList<QRegion> FRegionList;
      57     QList<QRegion> SRegionList;
      58 
      59 
      60 };
      61 
      62 #endif // HISTOGRAMVIEW_H
    • histogramview.cpp
        1 #include "histogramview.h"
        2 
        3 #include <QPainter>
        4 
        5 
        6 //当鼠标处在某个数据项的区域中,则返回此数据项的Index值,否则返回一个空的Index
        7 QModelIndex HistogramView::indexAt(const QPoint &point) const
        8 {
        9     QPoint newPoint(point.x(),point.y());
       10     QRegion region;
       11     //检查当前点是否处于第一列(男)数据的区域中
       12     foreach(region,MRegionList)//男列
       13     {
       14         if(region.contains(newPoint))
       15         {
       16             int row = MRegionList.indexOf(region);
       17             QModelIndex index = model()->index(row,1,rootIndex());
       18             return index;
       19         }
       20     }
       21 
       22     //检查当前点是否处于第二列(女)数据的区域中
       23     foreach(region,FRegionList)//女列
       24     {
       25         if(region.contains(newPoint))
       26         {
       27             int row = FRegionList.indexOf(region);
       28             QModelIndex index = model()->index(row,2,rootIndex());
       29             return index;
       30         }
       31     }
       32 
       33     //检查当前点是否处于第三列(合计)数据的区域中
       34     foreach(region,SRegionList) //合计 列
       35     {
       36         if(region.contains(newPoint))
       37         {
       38             int row=SRegionList.indexOf(region);
       39             QModelIndex index = model()->index(row,3,rootIndex());
       40             return index;
       41         }
       42     }
       43     return QModelIndex();
       44 }
       45 
       46 //为selections赋初值
       47 void HistogramView::setSelectionModel(QItemSelectionModel *selectionModel)
       48 {
       49     selections=selectionModel;
       50 }
       51 
       52 
       53 QRegion HistogramView::itemRegion(QModelIndex index)
       54 {
       55     QRegion region;
       56     if(index.column()==1) //
       57         region = MRegionList[index.row()];
       58     if(index.column()==2) //
       59         region = FRegionList[index.row()];
       60     if(index.column()==3) //退休
       61         region = SRegionList[index.row()];
       62 
       63     return region;
       64 }
       65 
       66 //完成柱状统计图的绘制
       67 void HistogramView::paintEvent(QPaintEvent *)
       68 {
       69     //以viewport()作为绘图设备新建一个QPainter对象
       70     QPainter painter(viewport());
       71     painter.setPen(Qt::black);
       72 
       73     int x0=40;
       74     int y0=250;
       75 
       76     //20-46行完成了x,y坐标轴的绘制,并标注坐标轴的变量
       77     //y坐标轴
       78     painter.drawLine(x0,y0,40,30);
       79     //箭头绘制
       80     painter.drawLine(38,32,40,30);
       81     painter.drawLine(40,30,42,32);
       82 
       83     painter.drawText(20,30,tr("人数"));
       84     //绘制坐标
       85     for(int i=0;i<5;i++)
       86     {
       87         painter.drawLine(1,i*50,1,i*50);
       88         painter.drawText(20,i*50,tr("%1").arg((5-i)*5));
       89     }
       90     //x坐标轴
       91     painter.drawLine(x0,y0,540,250);
       92     painter.drawLine(538,248,540,250);
       93     painter.drawLine(540,250,538,252);
       94     painter.drawText(545,250,tr("部门"));
       95 
       96     int posD=x0+20;
       97     int row;
       98     //遍历模式的行数
       99     for(row=0;row<model()->rowCount(rootIndex());row++)
      100     {
      101         //获得第0列
      102         QModelIndex index = model()->index(row,0,rootIndex());
      103         QString dep=model()->data(index).toString();
      104 
      105         painter.drawText(posD,y0+20,dep);
      106         posD += 50;
      107     }
      108 
      109 
      110     //50-75 完成第一列数据的柱状统计图的绘制
      111     //
      112     int posM=x0+20;
      113     for(row=0;row<model()->rowCount(rootIndex());row++)
      114     {
      115         //获得第一列
      116         QModelIndex index=model()->index(row,1,rootIndex());
      117         int male = model()->data(index).toDouble();
      118 
      119         int width = 10;
      120         //使用不同画刷颜色区别选择与未被选择的数据项
      121         if(selections->isSelected(index))
      122         {
      123             painter.setBrush(QBrush(Qt::blue,Qt::Dense3Pattern));
      124         }
      125         else
      126         {
      127             painter.setBrush(Qt::blue);
      128         }
      129 
      130         //根据当前数据项的值按比例绘制一个方形表示此数据项
      131         painter.drawRect(QRect(posM,y0-male*10,width,male*10));
      132         QRegion regionM(posM,y0-male*10,width,male*10);
      133         //将此数据所占据的区域保存到MRegionList列表中,为后面的数据项选择做准备
      134         MRegionList<<regionM;
      135         posM+=50;
      136     }
      137 
      138     //77-100    完成表格第二列数据的柱状统计图的绘制,同样,使用不同的画刷颜色区别
      139     //选中与未被选中的数据项,同时保存每个数据所占的区域至FRegionList列表中.
      140     //
      141     int posF=x0+30;
      142     for(row=0;row<model()->rowCount(rootIndex());row++)
      143     {
      144         QModelIndex index=model()->index(row,2,rootIndex());
      145         int female = model()->data(index).toDouble();
      146 
      147         int width = 10;
      148         if(selections->isSelected(index))
      149         {
      150             painter.setBrush(QBrush(Qt::red,Qt::Dense3Pattern));
      151         }
      152         else
      153         {
      154             painter.setBrush(Qt::red);
      155         }
      156 
      157         //左上角坐标,宽,长度
      158         painter.drawRect(QRect(posF,y0-female*10,width,female*10));
      159         //把区域添加到FRegionList
      160         QRegion regionM(posF,y0-female*10,width,female*10);
      161         FRegionList<<regionM;
      162         posF+=50;
      163     }
      164 
      165     //102-125    完成表格第三列数据的柱状统计图的绘制,同样,使用不同的画刷颜色区别
      166     //选中与未被选中的数据项,同时保存每个数据所占的区域至FRegionList列表中.
      167     //退休
      168     int posS=x0+40;
      169     for(row=0;row<model()->rowCount(rootIndex());row++)
      170     {
      171         QModelIndex index=model()->index(row,3,rootIndex());
      172         int retire = model()->data(index).toDouble();
      173 
      174         int width = 10;
      175         if(selections->isSelected(index))
      176         {
      177             painter.setBrush(QBrush(Qt::green,Qt::Dense3Pattern));
      178         }
      179         else
      180         {
      181             painter.setBrush(Qt::green);
      182         }
      183 
      184         painter.drawRect(QRect(posS,y0-retire*10,width,retire*10));
      185         QRegion regionS(posS,y0-retire*10,width,retire*10);
      186         SRegionList<<regionS;
      187         posS+=50;
      188     }
      189 }
      190 
      191 //柱状统计图可以被鼠标单击选择,选中后以不同的方式显示
      192 //在调用setSelection()函数时确定鼠标单击点是否在某个数据项的区域内,并设置选择项
      193 void HistogramView::mousePressEvent(QMouseEvent *event)
      194 {
      195     QAbstractItemView::mousePressEvent(event);
      196     setSelection(QRect(event->pos().x(),event->pos().y(),1,1),
      197                  QItemSelectionModel::SelectCurrent);
      198 }
      199 
      200 //当数据项变化时调用update()函数,重绘绘图设备,此函数是将其他View中的操作引起的数据项选择变化反映到自身View的显示中
      201 void HistogramView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
      202 {
      203     viewport()->update();
      204 }
      205 
      206 //当model中的数据更改时,调用绘图设备的update()函数进行更新,反映数据段的变化
      207 void HistogramView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
      208 {
      209     QAbstractItemView::dataChanged(topLeft,bottomRight);
      210     viewport()->update();
      211 }
      212 
      213 
      214 //将位于QRect内的数据项按照SelectionFlags(描述被选择的数据项以何种方式进行更新)
      215 //指定的方式进行更新.QItemSelectionModel类提供多种可用的SelectionFlags,常用的有
      216 //QItemSelectionModel::Select,QItemSelectionModel::Current等
      217 void HistogramView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags)
      218 {
      219     //获取总行数
      220     int rows = model()->rowCount(rootIndex());
      221     //获取总列数
      222     int columns = model()->columnCount(rootIndex());
      223     //用于保存被选中的数据项的Index值.此处只实现鼠标单击选择,而
      224     //没有实现鼠标拖拽框选,因此,鼠标动作只可能选中一个数据项.
      225     //若实现框选,则可使用QModelIndexList来保存所有被选中的数据项的Index值
      226     QModelIndex selectedIndex;
      227 
      228     //确定在rect中是否含有数据项.此处采用遍历的方式将每个数据项的区域与rect区域进行intersected操作
      229     //获得两者之间的交集.若此交集不为空则说明此数据项被选中,将它的Index赋值给selectedIndex
      230     for(int row=0;row<rows;++row)
      231     {
      232         for(int column=1;column<columns;++column)
      233         {
      234             QModelIndex index=model()->index(row,column,rootIndex());
      235             QRegion region = itemRegion(index);
      236 
      237             if(!region.intersected(rect).isEmpty())
      238             {
      239                 selectedIndex = index;
      240             }
      241         }
      242         if(selectedIndex.isValid())
      243         {
      244             //select()函数时在实现setSelection()函数时必须调用的
      245             selections->select(selectedIndex,flags);
      246         }
      247         else
      248         {
      249             QModelIndex noIndex;
      250             selections->select(noIndex,flags);
      251         }
      252     }
      253 }
      254 
      255 QModelIndex HistogramView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
      256 {
      257 
      258 }
      259 
      260 int HistogramView::horizontalOffset() const
      261 {
      262 
      263 }
      264 
      265 int HistogramView::verticalOffset() const
      266 {
      267 
      268 }
      269 
      270 bool HistogramView::isIndexHidden(const QModelIndex &index) const
      271 {
      272 
      273 }
      274 
      275 QRegion HistogramView::visualRegionForSelection(const QItemSelection &selection) const
      276 {
      277 
      278 }
      279 
      280 HistogramView::HistogramView(QWidget *parent)
      281         :QAbstractItemView(parent)
      282 {
      283 
      284 }
      285 
      286 QRect HistogramView::visualRect(const QModelIndex &index) const
      287 {
      288 
      289 }
      290 
      291 void HistogramView::scrollTo(const QModelIndex &index, QAbstractItemView::ScrollHint hint)
      292 {
      293 
      294 }
    • mainwindow.h
       1 #ifndef MAINWINDOW_H
       2 #define MAINWINDOW_H
       3 
       4 #include <QMainWindow>
       5 
       6 #include <QStandardItemModel>
       7 #include <QTableView>
       8 #include <QMenuBar>
       9 #include <QMenu>
      10 #include <QAction>
      11 #include <QSplitter>
      12 
      13 #include "histogramview.h"
      14 
      15 namespace Ui {
      16 class MainWindow;
      17 }
      18 
      19 class MainWindow : public QMainWindow
      20 {
      21     Q_OBJECT
      22 
      23 public:
      24     explicit MainWindow(QWidget *parent = 0);
      25     ~MainWindow();
      26     void createAction();
      27     void createMenu();
      28     void setupModel();
      29     void setupView();
      30 
      31 public:
      32     void openFile(QString);
      33 
      34 public slots:
      35     void slotOpen();
      36 
      37 
      38 private:
      39     Ui::MainWindow *ui;
      40 
      41     QMenu *fileMenu;
      42     QAction *openAct;
      43 
      44     QStandardItemModel *model;
      45     QTableView *table;
      46     QSplitter *splitter;
      47 
      48 private:
      49     HistogramView *histogram;
      50 };
      51 
      52 #endif // MAINWINDOW_H
    • mainwindow.cpp
        1 #include "mainwindow.h"
        2 #include "ui_mainwindow.h"
        3 
        4 #include <QFileDialog>
        5 #include <QFile>
        6 #include <QTextStream>
        7 #include <QStringList>
        8 
        9 
       10 
       11 MainWindow::MainWindow(QWidget *parent) :
       12     QMainWindow(parent),
       13     ui(new Ui::MainWindow)
       14 {
       15     ui->setupUi(this);
       16     //创建菜单项
       17     createAction();
       18     //创建菜单
       19     createMenu();
       20     //创建模型
       21     setupModel();
       22     //创建视图
       23     setupView();
       24 
       25     setWindowTitle(tr("View Example"));
       26     resize(600,600);
       27 
       28 }
       29 
       30 MainWindow::~MainWindow()
       31 {
       32     delete ui;
       33 }
       34 
       35 //创建菜单选项
       36 void MainWindow::createAction()
       37 {
       38     openAct = new QAction(tr("打开"),this);
       39 
       40     connect(openAct,SIGNAL(triggered(bool)),this,SLOT(slotOpen()));
       41 }
       42 
       43 
       44 //创建菜单
       45 void MainWindow::createMenu()
       46 {
       47     fileMenu=new QMenu(tr("文件"),this);
       48     fileMenu->addAction(openAct);
       49     menuBar()->addMenu(fileMenu);
       50 }
       51 
       52 //新建一个Model并设置表头数据
       53 void MainWindow::setupModel()
       54 {
       55     //创建模型4行4列
       56     model = new QStandardItemModel(4,4,this);
       57     model->setHeaderData(0,Qt::Horizontal,tr("部门"));
       58     model->setHeaderData(1,Qt::Horizontal,tr(""));
       59     model->setHeaderData(2,Qt::Horizontal,tr(""));
       60     model->setHeaderData(3,Qt::Horizontal,tr("退休"));
       61 
       62 
       63 }
       64 
       65 //创建视图
       66 void MainWindow::setupView()
       67 {
       68     //分割窗口
       69     splitter = new QSplitter;
       70     splitter->setOrientation(Qt::Vertical);
       71 
       72     //新建一个HistogramView对象,在splitter中绘制
       73     histogram = new HistogramView(splitter);
       74 
       75     //为HistogramView对象设置相同的Model
       76     histogram->setModel(model);
       77     //创建表格视图
       78     table = new QTableView;
       79     //为QTableView对象设置相同的Model
       80     table->setModel(model);
       81 
       82     //新建一个QItemSelectionModel对象作为QTableView对象使用的选择模型
       83     //使选择table可以在柱状图上面显示
       84     QItemSelectionModel *selectionModel=new QItemSelectionModel(model);
       85     table->setSelectionModel(selectionModel);
       86     histogram->setSelectionModel(selectionModel);
       87 
       88     //添加table和histogram
       89     splitter->addWidget(table);
       90     splitter->addWidget(histogram);
       91 
       92 
       93     //设置中心控件
       94     setCentralWidget(splitter);
       95 
       96     //连接选择模型的selectionChanged()信号与HistogramView对象的SelectionChanged()槽函数,以便使
       97     //QTableView对象中的选择变化能够反映到table和自定义的HistogramView对象的显示中
       98     connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
       99             table,SLOT(selectionChanged(QItemSelection,QItemSelection)));
      100     connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
      101             histogram,SLOT(selectionChanged(QItemSelection,QItemSelection)));
      102 }
      103 
      104 //打开文件并读取
      105 void MainWindow::openFile(QString path)
      106 {
      107     //读文件
      108     if(!path.isEmpty())
      109     {
      110         //根据路径打开文件
      111         QFile file(path);
      112         //以只读文本方式打开
      113         if(file.open(QFile::ReadOnly | QFile::Text))
      114         {
      115             //创建文件流
      116             QTextStream stream(&file);
      117             //保存读取的每一行
      118             QString line;
      119 
      120             //移除当前所有的行
      121             model->removeRows(0,model->rowCount(QModelIndex()),
      122                               QModelIndex());
      123             int row = 0;
      124             do
      125             {
      126                 //依次读取每一行
      127                 line = stream.readLine();
      128                 //如果读取的不为空
      129                 if(!line.isEmpty())
      130                 {
      131                     //插入一行数据
      132                     model->insertRows(row,1,QModelIndex());
      133                     //根据逗号拆分成很多部分
      134                     QStringList pieces = line.split(",",QString::SkipEmptyParts);
      135                     //分别填充第row行,0,1,2,3列
      136                     model->setData(model->index(row,0,QModelIndex()),
      137                                    pieces.value(0));
      138                     model->setData(model->index(row,1,QModelIndex()),
      139                                    pieces.value(1));
      140                     model->setData(model->index(row,2,QModelIndex()),
      141                                    pieces.value(2));
      142                     model->setData(model->index(row,3,QModelIndex()),
      143                                    pieces.value(3));
      144                     row++;
      145                 }
      146 
      147             }while(!line.isEmpty());
      148             file.close();
      149         }
      150     }
      151 }
      152 
      153 //与打开菜单项相对应的槽函数
      154 void MainWindow::slotOpen()
      155 {
      156     QString name;
      157     name = QFileDialog::getOpenFileName(this,"打开",".","histogram files(*.txt)");
      158     if(!name.isEmpty())
      159     {
      160         openFile(name);
      161     }
      162 }
    • main.cpp
       1 #include "mainwindow.h"
       2 #include <QApplication>
       3 
       4 int main(int argc, char *argv[])
       5 {
       6     QApplication a(argc, argv);
       7     MainWindow w;
       8     w.show();
       9 
      10     return a.exec();
      11 }

    4  代理

      在表格中嵌入各种不同控件,通过表格中的控件对编辑的内容进行限定.通常情况下,这种在表格中插入控件的方式,控件始终显示.当表格中控件数据较多时,将影响表格的美观.此时,可以利用Delegate的方式实现同样的效果,控件只有在需要编辑数据项的时候才会显示,从而解决了上述问题.

    运行效果

    • datadelegate.h
       1 #ifndef DATADELEGATE_H
       2 #define DATADELEGATE_H
       3 
       4 #include <QItemDelegate>
       5 
       6 class DataDelegate : public QItemDelegate
       7 {
       8     Q_OBJECT
       9 
      10 public:
      11     DataDelegate(QObject *parent=0);
      12     //完成创建控件的工作,创建由参数中的QModelIndex对象指定的表项数据的编辑控件
      13     //并对控件的内容进行限定
      14     QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
      15     //设置控件显示的数据,将Model中的数据更新至Delegate中,相当于一个初始化工作
      16     void setEditorData(QWidget *editor,const QModelIndex &index) const;
      17     //将Deletate中对数据的改变更新至Model中
      18     void setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index) const;
      19     //更新控件区的显示
      20     void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const;
      21 };
      22 
      23 #endif // DATADELEGATE_H
    • datadelegate.cpp
       1 #include "datadelegate.h"
       2 
       3 #include <QDateTimeEdit>
       4 
       5 DataDelegate::DataDelegate(QObject *parent)
       6     : QItemDelegate(parent)
       7 {
       8 
       9 }
      10 
      11 //完成创建控件的工作,创建由参数中的QModelIndex对象指定的表项数据的编辑控件
      12 //并对控件的内容进行限定
      13 QWidget *DataDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
      14 {
      15     //新建一个QDataTimeEdit对象作为编辑时的输入控件
      16     QDateTimeEdit *editor = new QDateTimeEdit(parent);
      17     //设置此QDateTimeEdit对象的显示格式为yyyy-MM-dd,此为ISO标准显示方式
      18     //日期的显示格式有很多种,可设定为:
      19     //yy.MM.dd  14.01.01
      20     //d.MM.yyyy 1.01.2014
      21     //其中,y表示年,M表示月份(必须大写),d表示日
      22     editor->setDisplayFormat("yyyy-MM-dd");
      23     //设置日历选择的显示以Popup的方式,即下拉菜单方式显示
      24     editor->setCalendarPopup(true);
      25     //调用QObject类的installEventFilter()函数安装事件过滤器,使DataDelegate
      26     //能够捕获QDateTimeEdit对象的事件
      27     editor->installEventFilter(const_cast<DataDelegate *>(this));
      28     return editor;
      29 
      30 }
      31 
      32 //设置控件显示的数据,将Model中的数据更新至Delegate中,相当于一个初始化工作
      33 void DataDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
      34 {
      35     //获取指定index数据项的数据.调用QModelIndex的model()函数可以获得提供index的Model对象
      36     //data()函数返回的是一个QVariant对象,toString()函数将它转换为一个QString类型数据
      37     QString dateStr=index.model()->data(index).toString();
      38     //通过QDate的fromString()函数将以QString类型表示的日期数据转换为QDate类型.
      39     //Qt::ISODate表示QDate类型的日期是以ISO格式保存的,这样最终转换获得的QDate数据也是ISO格式
      40     //使控件显示与表格显示保持一致
      41     QDate date = QDate::fromString(dateStr,Qt::ISODate);
      42 
      43     //将editor转换为QDateTimeEdit对象,以获得编辑控件的对象指针
      44     QDateTimeEdit *edit=static_cast<QDateTimeEdit*>(editor);
      45     //设置控件的显示数据
      46     edit->setDate(date);
      47 }
      48 
      49 //将Deletate中对数据的改变更新至Model中
      50 void DataDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
      51 {
      52     //通过紧缩转换获得编辑控件的对象指针
      53     QDateTimeEdit *edit = static_cast<QDateTimeEdit*>(editor);
      54     //获得编辑控件中的数据更新
      55     QDate date = edit->date();
      56     //调用setDat()函数将数据修改更新到Model中
      57     model->setData(index,QVariant(date.toString(Qt::ISODate)));
      58 }
      59 
      60 //更新控件区的显示
      61 void DataDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
      62 {
      63     editor->setGeometry(option.rect);
      64 }
    • combodelegate.h
       1 #ifndef COMBODELEGATE_H
       2 #define COMBODELEGATE_H
       3 
       4 #include <QItemDelegate>
       5 
       6 class ComboDelegate : public QItemDelegate
       7 {
       8     Q_OBJECT
       9 
      10 public:
      11     ComboDelegate(QObject *parent=0);
      12 
      13     //完成创建控件的工作,创建由参数中的QModelIndex对象指定的表项数据的编辑控件
      14     //并对控件的内容进行限定
      15     QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
      16     //设置控件显示的数据,将Model中的数据更新至Delegate中,相当于一个初始化工作
      17     void setEditorData(QWidget *editor,const QModelIndex &index) const;
      18     //将Deletate中对数据的改变更新至Model中
      19     void setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index) const;
      20     //更新控件区的显示
      21     void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const;
      22 };
      23 
      24 
      25 
      26 #endif // COMBODELEGATE_H
    • combodelegate.cpp
       1 #include "combodelegate.h"
       2 #include <QComboBox>
       3 
       4 ComboDelegate::ComboDelegate(QObject *parent)
       5         :QItemDelegate(parent)
       6 {
       7 
       8 }
       9 
      10 //创建一个QComboBox控件,并插入可显示的条目,安装事件过滤器
      11 QWidget *ComboDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
      12 {
      13     QComboBox *editor = new QComboBox(parent);
      14     editor->addItem("工人");
      15     editor->addItem("农民");
      16     editor->addItem("医生");
      17     editor->addItem("律师");
      18     editor->addItem("军人");
      19 
      20     editor->installEventFilter(const_cast<ComboDelegate*>(this));
      21     return editor;
      22 }
      23 
      24 //更新Delegate控件的数据显示(双击时调用)
      25 void ComboDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
      26 {
      27 
      28     QString str = index.model()->data(index).toString();
      29 
      30     QComboBox *box = static_cast<QComboBox *>(editor);
      31     int i=box->findText(str);
      32     box->setCurrentIndex(i);
      33 }
      34 
      35 
      36 //setModelData()函数中更新了Model中的数据
      37 void ComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
      38 {
      39     QComboBox *box = static_cast<QComboBox*>(editor);
      40 
      41     QString str = box->currentText();
      42     model->setData(index,str);
      43 }
      44 
      45 //更新控件区的显示区域
      46 void ComboDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
      47 {
      48     editor->setGeometry(option.rect);
      49 }
    • spindelegate.h
       1 #ifndef SPINDELEGATE_H
       2 #define SPINDELEGATE_H
       3 
       4 #include <QItemDelegate>
       5 
       6 class SpinDelegate : public QItemDelegate
       7 {
       8 public:
       9     SpinDelegate(QObject *parent = 0);
      10 
      11     //完成创建控件的工作,创建由参数中的QModelIndex对象指定的表项数据的编辑控件
      12     //并对控件的内容进行限定
      13     QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
      14     //设置控件显示的数据,将Model中的数据更新至Delegate中,相当于一个初始化工作
      15     void setEditorData(QWidget *editor,const QModelIndex &index) const;
      16     //将Deletate中对数据的改变更新至Model中
      17     void setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index) const;
      18     //更新控件区的显示
      19     void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const;
      20 };
      21 
      22 
      23 #endif // SPINDELEGATE_H
    • spindelegate.cpp
       1 #include "spindelegate.h"
       2 
       3 #include <QSpinBox>
       4 
       5 SpinDelegate::SpinDelegate(QObject *parent)
       6         :QItemDelegate(parent)
       7 {
       8 
       9 }
      10 
      11 QWidget *SpinDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
      12 {
      13     QSpinBox *editor = new QSpinBox(parent);
      14     editor->setRange(0,10000);
      15     editor->installEventFilter(const_cast<SpinDelegate*>(this));
      16     return editor;
      17 }
      18 
      19 void SpinDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
      20 {
      21     int value = index.model()->data(index).toInt();
      22     QSpinBox *box = static_cast<QSpinBox *>(editor);
      23     box->setValue(value);
      24 }
      25 
      26 void SpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
      27 {
      28     QSpinBox *box = static_cast<QSpinBox*>(editor);
      29     int value = box->value();
      30 
      31     model->setData(index,value);
      32 }
      33 
      34 void SpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
      35 {
      36     editor->setGeometry(option.rect);
      37 }
    • main.cpp
       1 #include "mainwindow.h"
       2 #include <QApplication>
       3 
       4 #include <QApplication>
       5 #include <QStandardItemModel>
       6 #include <QTableView>
       7 #include <QFile>
       8 #include <QTextStream>
       9 
      10 #include "datadelegate.h"
      11 #include "combodelegate.h"
      12 #include "spindelegate.h"
      13 
      14 int main(int argc, char *argv[])
      15 {
      16     QApplication a(argc, argv);
      17 
      18     QStandardItemModel model(4,4);
      19     QTableView tableView;
      20     tableView.setModel(&model);
      21 
      22 
      23     DataDelegate dateDelegate;
      24     //第一列与dataDelegate关联
      25     tableView.setItemDelegateForColumn(1,&dateDelegate);
      26 
      27     ComboDelegate ComboDelegate;
      28     tableView.setItemDelegateForColumn(2,&ComboDelegate);
      29 
      30     SpinDelegate SpinDelegate;
      31     tableView.setItemDelegateForColumn(3,&SpinDelegate);
      32 
      33     model.setHeaderData(0,Qt::Horizontal,QObject::tr("Name"));
      34     model.setHeaderData(1,Qt::Horizontal,QObject::tr("Birthday"));
      35     model.setHeaderData(2,Qt::Horizontal,QObject::tr("Job"));
      36     model.setHeaderData(3,Qt::Horizontal,QObject::tr("Income"));
      37 
      38     QFile file("test.txt");
      39     if(file.open(QFile::ReadOnly|QFile::Text))
      40     {
      41         QTextStream stream(&file);
      42         QString line;
      43 
      44         model.removeRows(0,model.rowCount(QModelIndex()),QModelIndex());
      45 
      46         int row = 0;
      47         do
      48         {
      49             line = stream.readLine();
      50             if(!line.isEmpty())
      51             {
      52                 model.insertRows(row,1,QModelIndex());
      53                 QStringList pieces = line.split(",",QString::SkipEmptyParts);
      54                 model.setData(model.index(row,0,QModelIndex()),pieces.value(0));
      55                 model.setData(model.index(row,1,QModelIndex()),pieces.value(1));
      56                 model.setData(model.index(row,2,QModelIndex()),pieces.value(2));
      57                 model.setData(model.index(row,3,QModelIndex()),pieces.value(3));
      58                 row++;
      59             }
      60         }while(!line.isEmpty());
      61 
      62         file.close();
      63     }
      64 
      65     tableView.setWindowTitle(QObject::tr("Delegate"));
      66     tableView.show();
      67 
      68     return a.exec();
      69 }
  • 相关阅读:
    黑马程序员_使用Jquery实现AJAX功能
    BootStrap 推荐网站
    工具类
    ExtJS 模块案例(增删改查)
    sql server 经典语句。~转 (入门必看)
    sql 时间格式转换
    转载wuhuacong(伍华聪)的专栏 利用Aspose.Word控件实现Word文档的操作 (留作笔记)
    c#操作Word文件 导出数据到word文档 (table 书签方式)
    ExtJs之格式化(Ext.util.Format) ~转
    查询/修改XML里某个字段的值
  • 原文地址:https://www.cnblogs.com/xiaochi/p/8850325.html
Copyright © 2020-2023  润新知