Qt5入门学习——模型/视图结构

简介: Qt5入门学习——模型/视图结构

文章目录

概述

基本概念

简单文件目录浏览器【简单示例】

模型(Model)

自定义模型【示例】

视图(View)

表格数据显示【示例】

代理(Delegate)

利用Delegate设计表格控件【示例】


Qt的模型/视图结构分为三部分:模型(Model)、视图(View)和代理(Delegate)。其中,模型与数据源通信,并为其他部件提供接口;而视图从模型中获得用来引用数据条目的模型索引(Model Index)。在视图中,代理负责绘制数据条目,当编辑条目时,代理和模型直接进行通信。模型/视图/代理之间通过信号和槽进行通信,

20200319155111579.png

概述

基本概念

  • 模型(model)

InterView框架中的所有模型都基于抽象基类QAbstractItemModel类,此类由QProxyModel、 QAbstractListModel、 QAbstractTableModel、QAbstractProxyModel、 QDirModel、 QFileSystemModel、QHelpContentModel 和 QStandardItemModel类继承。其中, QAbstractListModel

类和QAbstractTableModel类是列表和表格模型的抽象基类,如果需要实现列表或表格模型,则应从这两个类继承。完成QStringList存储的QStringListModel继承自QAbstractListModel类,而与数据库有关的QSqlQueryModel类继承自QAbstractTableModel类; QAbstractProxyModel类是代理模型的抽象类;QDirModel类是文件和目录的存储模型。


  • 视图(view)

InterView框架中的所有视图都基于抽象基类QAbstractItemView类,此类由QColumnView、 QHeaderView、 QListView、 QTableView和QTreeView类继承。其中, QListView类由QUndoView类和QListWidget类继承; QTableView类由QTableWidget类继承; QTreeView类由QTreeWidget类继承。而QListWidget类、QTableWidget类和QTreeWidget类实际上已经包含了数据,是模型/视图集成在一起的类。


  • 代理(delegate)

InterView框架中的所有代理都基于抽象基类QAbstractItemDelegate类,此类由QItemDelegate 和 QStyledItemDelegate类继承。其中, QItemDelegate类由表示数据库中关系代理的QSqlRelationalDelegate类继承。


简单文件目录浏览器【简单示例】

简单实现一个文件目录浏览器。只需要编辑main.cpp文件在项目文件中即可。


  • main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QAbstractItemModel>
#include <QAbstractItemView>
#include <QItemSelectionModel>
#include <QDirModel>
#include <QTreeView>
#include <QListView>
#include <QTableView>
#include <QSplitter>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //新建一个QDirModel对象,为数据访问做准备,此外还可以设置过滤器。
    //QDirmodel为访问本地文件系统提供数据模型,提供了新建、删除、创建目录等一系列与文件操作相关的函数。
    QDirModel model;
    /* 新建三种不同的View对象,以便文件目录可以以三种不同的方式显示 */
    QTreeView tree;
    QListView list;
    QTableView table;
    //调用setModel函数设置View对象的model为QDirmodel。
    tree.setModel(&model);
    list.setModel(&model);
    table.setModel(&model);
    //设置QTreeView对象的选择方式为多选方式。
    tree.setSelectionMode(QAbstractItemView::MultiSelection);
    //设置QListView对象与QTreeView对象使用相同的选择模型。
    list.setSelectionModel(tree.selectionModel());
    //设置QTableView对象与QTreeView对象使用相同的选择模型。
    table.setSelectionModel(tree.selectionModel());
    QObject::connect(&tree,SIGNAL(doubleClicked(QModelIndex)),&list,
                           SLOT(setRootIndex(QModelIndex)));
    //实现双机对象中某一目录时显示此目录下的所以文件和目录,需要连接QTreeView对象的doubleClicked信号
    //与QListView对象和QTableView对象的setRootIndex槽函数。
    QObject::connect(&tree,SIGNAL(doubleClicked(QModelIndex)),&table,
                           SLOT(setRootIndex(QModelIndex)));
    QSplitter *splitter = new QSplitter;
    splitter->addWidget(&tree);
    splitter->addWidget(&list);
    splitter->addWidget(&table);
    splitter->setWindowTitle(QObject::tr("Model/View"));
    splitter->show();
    //MainWindow w;
    //w.show();
    return a.exec();
}


  • 执行结果

20200319162027115.gif

模型(Model)

通过实现将数值代码转换为文字的模型来介绍使用自定义模型。此模型中保存了不同军中的各种武器。

在model中会用到以下item主要的角色:


常量 描述

Qt::DisplayRole 显示文字

Qt::DecorationRole 绘制装饰数据(通常是图标)

Qt::EditRole 在编辑器中编辑的数据

Qt::ToolTipRole 工具提示

Qt::StatusTipRole 状态栏提示

Qt::WhatsThisRole What’s This文字

Qt::SizeHintRole 尺寸提示

Qt::FontRole 默认代理的绘制使用的字体

Qt::TextAlignmentRole 默认代理的对齐方式

Qt::BackgroundRole 默认代理的背景画刷

Qt::ForegroundRole 默认代理的前景画刷

Qt::CheckStateRole 默认代理的检查框状态

Qt::UserRole 用户自定义的数据的起始位置

自定义模型【示例】

  • 项目结构

20200319163305829.png


  • main.cpp


#include "mainwindow.h"
#include <QApplication>
#include "modelex.h"
#include <QTableView>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ModelEx modelEx;
    QTableView view;
    view.setModel(&modelEx);
    view.setWindowTitle(QObject::tr("modelEx"));
    view.resize(400,400);
    view.show();
    //MainWindow w;
    //w.show();
    return a.exec();
}


  • modelex.h
#ifndef MODELEX_H
#define MODELEX_H
#include <QAbstractTableModel>
#include <QVector>
#include <QMap>
#include <QStringList>
class ModelEx : public QAbstractTableModel
{
public:
    explicit ModelEx(QObject *parent=0);
    //虚函数声明          //(a)
    virtual int rowCount(const QModelIndex &parent=QModelIndex()) const;
    virtual int columnCount(const QModelIndex &parent=QModelIndex()) const;
    QVariant data(const QModelIndex &index, int role) const;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const;
signals:
public slots:
private:
    QVector<short> army;
    QVector<short> weaponType;
    QMap<short,QString> armyMap;  //使用QMap数据结构保存“数值—文字”的映射
    QMap<short,QString> weaponTypeMap;
    QStringList  weapon;
    QStringList  header;
    void populateModel();   //完成表格数据的初始化填充
};
#endif // MODELEX_H


  • modelex.cpp
#include "modelex.h"
ModelEx::ModelEx(QObject *parent):QAbstractTableModel(parent)
{
    armyMap[1]=tr("空军");
    armyMap[2]=tr("海军");
    armyMap[3]=tr("陆军");
    armyMap[4]=tr("海军陆战队");
    weaponTypeMap[1]=tr("轰炸机");
    weaponTypeMap[2]=tr("战斗机");
    weaponTypeMap[3]=tr("航空母舰");
    weaponTypeMap[4]=tr("驱逐舰");
    weaponTypeMap[5]=tr("直升机");
    weaponTypeMap[6]=tr("坦克");
    weaponTypeMap[7]=tr("两栖攻击舰");
    weaponTypeMap[8]=tr("两栖战车");
    populateModel();
}
void ModelEx::populateModel()
{
    header<<tr("军种")<<tr("种类")<<tr("武器");
    army<<1<<2<<3<<4<<2<<4<<3<<1;
    weaponType<<1<<3<<5<<7<<4<<8<<6<<2;
    weapon<<tr("B-2")<<tr("尼米兹级")<<tr("阿帕奇")<<tr("黄蜂级")
            <<tr("阿利伯克级")<<tr("AAAV")<<tr("M1A1")<<tr("F-22");
}
int ModelEx::columnCount(const QModelIndex &parent) const
{  return 3;    }
int ModelEx::rowCount(const QModelIndex &parent) const
{
    return army.size();
}
QVariant ModelEx::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();
    if(role==Qt::DisplayRole)    //(a)
    {
        switch(index.column())
        {
        case 0:
            return armyMap[army[index.row()]];
            break;
        case 1:
            return weaponTypeMap[weaponType[index.row()]];
            break;
        case 2:
            return weapon[index.row()];
        default:
            return QVariant();
        }
    }
    return QVariant();
}
QVariant ModelEx::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role==Qt::DisplayRole&&orientation==Qt::Horizontal)
           return header[section];
    return QAbstractTableModel::headerData(section,orientation,role);
}


  • 执行结果

20200319163305829.png

视图(View)

通过自定义的view实现一个对TableModel的表格数据进行显示的柱状图统计图示例。


表格数据显示【示例】

  • 项目结构


20200319164614181.png

  • main.cpp


#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}


  • mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStandardItemModel>
#include <QTableView>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QSplitter>
#include "histogramview.h"
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void createAction();
    void createMenu();
    void setupModel();
    void setupView();
    void openFile(QString);
public slots:
    void slotOpen();
private:
    QMenu *fileMenu;
    QAction *openAct;
    QStandardItemModel *model;
    QTableView *table;
    QSplitter *splitter;
    HistogramView *histogram;
};
#endif // MAINWINDOW_H


  • mainwindow.cpp
#include "mainwindow.h"
#include <QItemSelectionModel>
#include <QFileDialog>
#include <QFile>
#include <QTextStream>
#include <QStringList>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    createAction();
    createMenu();
    setupModel();
    setupView();
    setWindowTitle(tr("View Example"));
    resize(600,600);
}
MainWindow::~MainWindow()
{
}
void MainWindow::createAction()
{
    openAct = new QAction(tr("打开"),this);
    connect(openAct,SIGNAL(triggered()),this,SLOT(slotOpen()));
}
void MainWindow::createMenu()
{
    fileMenu = new QMenu(tr("文件"),this);
    fileMenu->addAction(openAct);
    menuBar()->addMenu(fileMenu);
}
void MainWindow::setupModel()
{
    model = new QStandardItemModel(4,4,this);
    model->setHeaderData(0,Qt::Horizontal,tr("部门"));
    model->setHeaderData(1,Qt::Horizontal,tr("男"));
    model->setHeaderData(2,Qt::Horizontal,tr("女"));
    model->setHeaderData(3,Qt::Horizontal,tr("退休"));
}
void MainWindow::setupView()
{
    /*
    table = new QTableView;   //新建一个QTableView对象
    table->setModel(model);   //为QTableView对象设置相同的Model
    QItemSelectionModel *selectionModel=new QItemSelectionModel(model);
                                    //(a)
    table->setSelectionModel(selectionModel);
    connect(selectionModel,SIGNAL(selectionChanged(QItemSelection, ItemSelection)),table,SLOT(selectionChanged(QItemSelection,QItemSelection)));          //(b)
    splitter = new QSplitter;
    splitter->setOrientation(Qt::Vertical);
    splitter->addWidget(table);
    setCentralWidget(splitter);
    */
    splitter = new QSplitter;
    splitter->setOrientation(Qt::Vertical);
    histogram = new HistogramView(splitter);        //新建一个HistogramView对象
    histogram->setModel(model);                     //为HistogramView对象设置相同的Model
    table = new QTableView;
    table->setModel(model);
    QItemSelectionModel *selectionModel=new QItemSelectionModel (model);
    table->setSelectionModel(selectionModel);
    histogram->setSelectionModel(selectionModel); //(a)
    splitter->addWidget(table);
    splitter->addWidget(histogram);
    setCentralWidget(splitter);
    connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),table,SLOT(selectionChanged(QItemSelection,QItemSelection)));
    connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),histogram,SLOT(selectionChanged(QItemSelection,QItemSelection)));        //(b)
}
void MainWindow::slotOpen()
{
    QString name;
    name = QFileDialog::getOpenFileName(this,"打开",".","histogram files (*.txt)");
    if (!name.isEmpty())
          openFile(name);
}
void MainWindow::openFile(QString path)
{
    if (!path.isEmpty())
    {
        QFile file(path);
         if (file.open(QFile::ReadOnly | QFile::Text))
         {
             QTextStream stream(&file);
             QString line;
             model->removeRows(0,model->rowCount(QModelIndex()),
                   QModelIndex());
             int row = 0;
             do
             {
                 line = stream.readLine();
                 if (!line.isEmpty())
                 {
                        model->insertRows(row, 1, QModelIndex());
                        QStringList pieces = line.split(",", QString
                            ::SkipEmptyParts);
                        model->setData(model->index(row, 0, QModelIndex()),
                            pieces.value(0));
                        model->setData(model->index(row, 1, QModelIndex()),
                            pieces.value(1));
                        model->setData(model->index(row, 2, QModelIndex()),
                            pieces.value(2));
                        model->setData(model->index(row,3, QModelIndex()),
                            pieces.value(3));
                        row++;
                 }
             } while (!line.isEmpty());
           file.close();
         }
    }
}


  • histogramview.h
#ifndef HISTOGRAMVIEW_H
#define HISTOGRAMVIEW_H
#include <QAbstractItemView>
#include <QItemSelectionModel>
#include <QRegion>
#include <QMouseEvent>
class HistogramView : public QAbstractItemView
{
    Q_OBJECT
public:
    HistogramView(QWidget *parent=0);
    //虚函数声明
    QRect visualRect(const QModelIndex &index)const;
    void scrollTo(const QModelIndex &index,ScrollHint hint= EnsureVisible);
    QModelIndex indexAt(const QPoint &point)const;
    //为selections赋初值
    void setSelectionModel(QItemSelectionModel *selectionModel);
    QRegion itemRegion(QModelIndex index);
    void paintEvent(QPaintEvent *);
    void mousePressEvent(QMouseEvent *event);
protected slots:
    void selectionChanged(const QItemSelection &selected,
          const QItemSelection &deselected);
    void dataChanged(const QModelIndex &topLeft,
          const QModelIndex &bottomRight);
protected:
    //虚函数声明
    QModelIndex moveCursor(QAbstractItemView::CursorAction cursorAction,
          Qt::KeyboardModifiers modifiers);
    int horizontalOffset()const;
    int verticalOffset()const;
    bool isIndexHidden(const QModelIndex &index)const;
    void setSelection(const QRect &rect,QItemSelectionModel:: SelectionFlags flags);//(f)
    QRegion visualRegionForSelection(const QItemSelection &selection) const;
private:
    QItemSelectionModel *selections;      //(g)
    QList<QRegion> MRegionList;       //(h)
    QList<QRegion> FRegionList;
    QList<QRegion> SRegionList;
};
#endif // HISTOGRAMVIEW_H


  • histogramview.cpp
#include "histogramview.h"
#include <QPainter>
HistogramView::HistogramView(QWidget *parent):QAbstractItemView(parent)
{
}
// paintEvent()函数具体完成柱状统计图绘制的工作
void HistogramView::paintEvent(QPaintEvent *)
{
    QPainter painter(viewport());     //(a)
    painter.setPen(Qt::black);
    int x0=40;
    int y0=250;
    /* 完成了x、y坐标轴的绘制,并标注坐标轴的变量 */
    //y坐标轴
    painter.drawLine(x0,y0,40,30);
    painter.drawLine(38,32,40,30);
    painter.drawLine(40,30,42,32);
    painter.drawText(20,30,tr("人数"));
    for(int i=1;i<5;i++)
    {
        painter.drawLine(-1,-i*50,1,-i*50);
        painter.drawText(-20,-i*50,tr("%1").arg(i*5));
    }
    //x 坐标轴
    painter.drawLine(x0,y0,540,250);
    painter.drawLine(538,248,540,250);
    painter.drawLine(540,250,538,252);
    painter.drawText(545,250,tr("部门"));
    int posD=x0+20;
    int row;
    for(row=0;row<model()->rowCount(rootIndex());row++)
    {
        QModelIndex index=model()->index(row,0,rootIndex());
        QString dep=model()->data(index).toString();
        painter.drawText(posD,y0+20,dep);
        posD+=50;
    }
    /* 完成了表格第1列数据的柱状统计图的绘制 */
    //男
    int posM=x0+20;
    MRegionList.clear();
    for(row=0;row<model()->rowCount(rootIndex());row++)
    {
        QModelIndex index=model()->index(row,1,rootIndex());
        int male=model()->data(index).toDouble();
        int width=10;
        if(selections->isSelected(index))   //(b)
            painter.setBrush(QBrush(Qt::blue,Qt::Dense3Pattern));
        else
            painter.setBrush(Qt::blue);
        painter.drawRect(QRect(posM,y0-male*10,width,male*10));//(c)
        QRegion regionM(posM,y0-male*10,width,male*10);
        MRegionList.insert(row,regionM);            //(d)
        posM+=50;
    }
    /* 完成了表格第2列数据的柱状统计图的绘制 */   //(e)
    //女
    int posF=x0+30;
    FRegionList.clear();
    for(row=0;row<model()->rowCount(rootIndex());row++)
    {
        QModelIndex index=model()->index(row,2,rootIndex());
        int female=model()->data(index).toDouble();
        int width=10;
        if(selections->isSelected(index))
            painter.setBrush(QBrush(Qt::red,Qt::Dense3Pattern));
        else
            painter.setBrush(Qt::red);
        painter.drawRect(QRect(posF,y0-female*10,width,female*10));
        QRegion regionF(posF,y0-female*10,width,female*10);
        FRegionList.insert(row,regionF);
        posF+=50;
    }
    /* 完成了表格第3列数据的柱状统计图的绘制 */   //(f)
    //退休
    int posS=x0+40;
    SRegionList.clear();
    for(row=0;row<model()->rowCount(rootIndex());row++)
    {
        QModelIndex index=model()->index(row,3,rootIndex());
        int retire=model()->data(index).toDouble();
        int width=10;
        if(selections->isSelected(index))
            painter.setBrush(QBrush(Qt::green,Qt::Dense3Pattern));
        else
            painter.setBrush(Qt::green);
        painter.drawRect(QRect(posS,y0-retire*10,width,retire*10));
        QRegion regionS(posS,y0-retire*10,width,retire*10);
        SRegionList.insert(row,regionS);
        posS+=50;
    }
}
void HistogramView::dataChanged(const QModelIndex &topLeft,
       const QModelIndex &bottomRight)
{
    QAbstractItemView::dataChanged(topLeft,bottomRight);
    viewport()->update();
}
void HistogramView::setSelectionModel(QItemSelectionModel *selectionModel)
{
    selections=selectionModel;
}
void HistogramView::selectionChanged(const QItemSelection &selected,
      const QItemSelection &deselected)
{
    viewport()->update();
}
void HistogramView::mousePressEvent(QMouseEvent *event)
{
    QAbstractItemView::mousePressEvent(event);
    setSelection(QRect(event->pos().x(),event->pos().y(),1,1),QItemSelectionModel::SelectCurrent);
}
void HistogramView::setSelection(const QRect &rect,QItemSelectionModel::SelectionFlags flags)
{
    int rows = model()->rowCount(rootIndex());    //获取总行数
    int columns = model()->columnCount(rootIndex());  //获取总列数
    QModelIndex selectedIndex;
    for (int row=0; row<rows; ++row)
    {
        for (int column=1; column<columns; ++column)
        {
            QModelIndex index=model()->index(row,column,rootIndex());
            QRegion region=itemRegion(index);
            if (!region.intersected(rect).isEmpty())
                selectedIndex = index;
        }
    }
    if(selectedIndex.isValid())
        selections->select(selectedIndex,flags);
    else
    {
        QModelIndex noIndex;
        selections->select(noIndex,flags);
    }
}
QModelIndex HistogramView::indexAt(const QPoint &point)const
{
    QPoint newPoint(point.x(),point.y());
    QRegion region;
    // 男 列
    foreach(region,MRegionList)
    {
        if (region.contains(newPoint))
        {
            int row = MRegionList.indexOf(region);
            QModelIndex index = model()->index(row,1,rootIndex());
            return index;
        }
    }
    // 女 列
    foreach(region,FRegionList)
    {
        if (region.contains(newPoint))
        {
            int row = FRegionList.indexOf(region);
            QModelIndex index = model()->index(row,2,rootIndex());
            return index;
        }
    }
    // 合计 列
    foreach(region,SRegionList)
    {
        if (region.contains(newPoint))
        {
            int row = SRegionList.indexOf(region);
            QModelIndex index = model()->index(row,3,rootIndex());
            return index;
        }
    }
    return QModelIndex();
}
QRect HistogramView::visualRect(const QModelIndex &index)const{}
void HistogramView::scrollTo(const QModelIndex &index,ScrollHint){}
QModelIndex HistogramView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers){}
int HistogramView::horizontalOffset()const{}
int HistogramView::verticalOffset()const{}
bool HistogramView::isIndexHidden(const QModelIndex &index)const{}
QRegion HistogramView::visualRegionForSelection(const QItemSelection & selection)const{}
QRegion HistogramView::itemRegion(QModelIndex index)
{
    QRegion region;
    if (index.column() == 1)  //男
        region = MRegionList[index.row()];
    if (index.column() == 2)  //女
        region = FRegionList[index.row()];
    if (index.column() == 3)  //退休
        region = SRegionList[index.row()];
    return region;
}


  • 执行结果

20200319164520436.gif

代理(Delegate)

利用Delegate设计表格控件。


利用Delegate设计表格控件【示例】

  • 项目结构

2020031916575199.png

  • main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QStandardItemModel>
#include <QTableView>
#include <QFile>
#include <QTextStream>
#include "datedelegate.h"
#include "combodelegate.h"
#include "spindelegate.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QStandardItemModel model(4,4);
    QTableView tableView;
    tableView.setModel(&model);
    DateDelegate dateDelegate;
    tableView.setItemDelegateForColumn(1,&dateDelegate);
    ComboDelegate comboDelegate;
    tableView.setItemDelegateForColumn(2,&comboDelegate);
    SpinDelegate spinDelegate;
    tableView.setItemDelegateForColumn(3,&spinDelegate);
    model.setHeaderData(0,Qt::Horizontal,QObject::tr("姓名"));
    model.setHeaderData(1,Qt::Horizontal,QObject::tr("生日"));
    model.setHeaderData(2,Qt::Horizontal,QObject::tr("职业"));
    model.setHeaderData(3,Qt::Horizontal,QObject::tr("收入"));
    QFile file("test.txt");
    if(file.open(QFile::ReadOnly|QFile::Text))
    {
        QTextStream stream(&file);
        QString line;
        model.removeRows(0,model.rowCount(QModelIndex()),QModelIndex());
        int row =0;
        do{
               line = stream.readLine();
               if(!line.isEmpty())
               {
                   model.insertRows(row,1,QModelIndex());
                   QStringList pieces = line.split(",",QString::SkipEmptyParts);
                   model.setData(model.index(row,0,QModelIndex()), pieces
                         .value(0));
                   model.setData(model.index(row,1,QModelIndex()), pieces
                         .value(1));
                   model.setData(model.index(row,2,QModelIndex()), pieces
                         .value(2));
                   model.setData(model.index(row,3,QModelIndex()), pieces
                         .value(3));
                   row++;
               }
        }while(!line.isEmpty());
        file.close();
    }
    tableView.setWindowTitle(QObject::tr("Delegate"));
    tableView.show();
    //MainWindow w;
    //w.show();
    return a.exec();
}


  • spindelegate.h
#ifndef SPINDELEGATE_H
#define SPINDELEGATE_H
#include <QItemDelegate>
class SpinDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    SpinDelegate(QObject *parent = 0);
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex  &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
#endif // SPINDELEGATE_H


  • spindelegate.cpp
#include "spindelegate.h"
#include <QSpinBox>
SpinDelegate::SpinDelegate(QObject *parent):QItemDelegate(parent)
{
}
QWidget *SpinDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
    QSpinBox *editor = new QSpinBox(parent);
    editor->setRange(0,10000);
    editor->installEventFilter(const_cast<SpinDelegate*>(this));
    return editor;
}
void SpinDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
    int value =index.model()->data(index).toInt();
    QSpinBox *box = static_cast<QSpinBox*>(editor);
    box->setValue(value);
}
void SpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const
{
    QSpinBox *box = static_cast<QSpinBox*>(editor);
    int value = box->value();
    model->setData(index,value);
}
void SpinDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
    editor->setGeometry(option.rect);
}


  • datedelegate.h
#ifndef DATEDELEGATE_H
#define DATEDELEGATE_H
#include <QItemDelegate>
class DateDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    DateDelegate(QObject *parent = 0);
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem & option, const QModelIndex &index) const;    //(a)
    void setEditorData(QWidget *editor, const QModelIndex &index) const;              //(b)
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;  //将Delegate中对数据的改变更新至Model中
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem & option, const QModelIndex &index) const;  //更新控件区的显示
};
#endif // DATEDELEGATE_H
  • datedelegate.cpp
#include "datedelegate.h"
#include <QDateTimeEdit>
DateDelegate::DateDelegate(QObject *parent):QItemDelegate(parent)
{
}
QWidget *DateDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
    QDateTimeEdit *editor = new QDateTimeEdit(parent);  //(a)
    editor->setDisplayFormat("yyyy-MM-dd");     //(b)
    editor->setCalendarPopup(true);       //(c)
    editor->installEventFilter(const_cast<DateDelegate*>(this));
                                                            //(d)
    return editor;
}
void DateDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
   QString dateStr= index.model()->data(index).toString();  //(a)
   QDate date = QDate::fromString(dateStr,Qt::ISODate);  //(b)
   QDateTimeEdit *edit=static_cast<QDateTimeEdit*>(editor); //(c)
   edit->setDate(date);                                     //设置控件的显示数据
}
void DateDelegate::setModelData(QWidget *editor,QAbstractItemModel *model, const QModelIndex &index) const
{
    QDateTimeEdit *edit=static_cast<QDateTimeEdit*>(editor);//(a)
    QDate date = edit->date();        //(b)
    model->setData(index,QVariant(date.toString(Qt::ISODate)));//(c)
}
void DateDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}


  • combodelegate.h
#ifndef COMBODELEGATE_H
#define COMBODELEGATE_H
#include <QItemDelegate>
class ComboDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    ComboDelegate(QObject *parent = 0);
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
#endif // COMBODELEGATE_H


  • combodelegate.cpp
#include "combodelegate.h"
#include <QComboBox>
ComboDelegate::ComboDelegate(QObject *parent):QItemDelegate(parent)
{
}
QWidget *ComboDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
    QComboBox *editor = new QComboBox(parent);
    editor->addItem("工人");
    editor->addItem("农民");
    editor->addItem("医生");
    editor->addItem("律师");
    editor->addItem("军人");
    editor->installEventFilter(const_cast<ComboDelegate*>(this));
    return editor;
}
void ComboDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
    QString str =index.model()->data(index).toString();
    QComboBox *box = static_cast<QComboBox*>(editor);
    int i=box->findText(str);
    box->setCurrentIndex(i);
}
void ComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QComboBox *box = static_cast<QComboBox*>(editor);
    QString str = box->currentText();
    model->setData(index,str);
}
void ComboDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
    editor->setGeometry(option.rect);
}


  • 执行结果

20200319165725516.gif

相关文章
|
3月前
Qt类结构分析
Qt类结构分析
59 3
|
24天前
|
存储 SQL 数据库连接
【QT速成】半小时入门QT6之QT前置知识扫盲(二)
【QT速成】半小时入门QT6之QT前置知识扫盲(二)
91 13
|
30天前
|
存储 SQL 数据库连接
【QT速成】半小时入门QT6之QT前置知识扫盲(二)
【QT速成】半小时入门QT6之QT前置知识扫盲(二)
|
30天前
|
数据可视化 编译器 API
【QT速成】半小时入门QT6之QT前置知识扫盲(一)
【QT速成】半小时入门QT6之QT前置知识扫盲(一)
|
2月前
|
定位技术 Go 开发工具
dynamic-situational-awareness-qt学习记录
本文是作者yantuguiguziPGJ关于dynamic-situational-awareness-qt学习记录的分享,介绍了在Qt学习过程中发现的qml资源丰富的代码仓库,并提供了资源路径和相关的安装、配置步骤,涉及的内容有数字地球、GIS纹理等,同时提供了相关链接和git命令来克隆代码仓库和ArcGIS Runtime SDK for Qt的安装说明。
|
28天前
|
编译器 API C语言
【QT速成】半小时入门QT6之QT前置知识扫盲(一)
【QT速成】半小时入门QT6之QT前置知识扫盲(一)
106 0
|
5月前
|
编译器 C++
(10)Qt对象模型
(10)Qt对象模型
|
5月前
|
计算机视觉
【轻松入门】OpenCV4.8 + QT5.x开发环境搭建
【轻松入门】OpenCV4.8 + QT5.x开发环境搭建
80 0
【轻松入门】OpenCV4.8 + QT5.x开发环境搭建
|
4月前
|
C++
Qt中的信号与槽如何学习?(包括自定义信号)这篇文章告诉你
以现实中的事件来举例的话,例如有两把不同颜色的信号枪,分别是红色,绿色,打响不通颜色的信号枪会触发不同的槽发生,比如说打响红色这个人就跑步,绿色就走步,但是还有一个很重要的机制,那就是连接,我们需要把信号枪去跟这个人的动作连接起来。 如果上面理解没问题的话我们可以把信号和槽看成两个工具,我们最重要的是如何去把这两个工具连接起来。 它的作用可以让我们更加灵活的去使用不同窗口间的切换以及某些事件的连接。
|
4月前
|
开发者
Qt中的事件该如何学习?(附带案例)
事件是Qt中比较重要的一部分,在初期如果理解不当学习可能会比较困难,这里提一嘴当初教我的那位老师水平是真的高,让我很轻易的就理解了事件的概念。 在平时我们见到那些界面上的某些快捷键就有可能是事件做的,例如ESC关闭窗口,Enter提交或者登录这种类似的,这也是事件的强大之处。
110 0