Model/View中自定义Model——入门篇

本文详细介绍了如何使用QAbstractTableModel自定义模型,并配合QTableView展示数据,以及如何为表格中的特定列使用自定义视图委托,如下拉列表、日期选择器和滑动条。
摘要由CSDN通过智能技术生成

1、基于QAbstractTableModel自定义Model

2、自定义视图委托Delegate,以表格的方式呈现,委托有下拉列表、日期和spinBox

一、基于QAbstractTableModel自定义Model

        使用自定义Model,配合QTableView  

ModelEx modelEx;
QTableView view;
view.setModel(&modelEx);
view.setWindowTitle(QObject::tr("modelEx"));
view.resize(400,400);
view.show();
#ifndef MODELEX_H
#define MODELEX_H

#include <QAbstractTableModel>
#include <QVector>
#include <QMap>
#include <QStringList>

class ModelEx : public QAbstractTableModel
{
    Q_OBJECT
public:
    explicit ModelEx(QObject *parent = 0);

    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<short,QString> weaponTypeMap;

    QStringList  weapon;
    QStringList  header;

    void populateModel();
};

#endif // MODELEX_H
#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();
}

//数据存储部分,这部分是最staple部分,也是逻辑较为复杂的部分
QVariant ModelEx::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    if(role==Qt::DisplayRole)
    {
        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);
}

二、使用自定义委托

#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);
    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("收入"));

    //创建标准的视图
    QTableView tableView;
    tableView.setModel(&model);

    //创建自定义委托,这三种委托的主要差别在于createEditor函数的实现
    DateDelegate dateDelegate;
    tableView.setItemDelegateForColumn(1,&dateDelegate);

    ComboDelegate comboDelegate;
    tableView.setItemDelegateForColumn(2,&comboDelegate);

    SpinDelegate spinDelegate;
    tableView.setItemDelegateForColumn(3,&spinDelegate);

    //导入数据到数据模型中
    QFile file("test.txt");
    if(file.open(QFile::ReadOnly|QFile::Text))
    {
        QTextStream stream(&file);
        QString line;

        //delete all the data
        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();
    
    return a.exec();
}

三种委托都是inherit from QItemDelegate

下面只列举其中一个委托的定义,其它委托类的定义可参考该定义

#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;
};
#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);
}


//


#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);
    editor->setDisplayFormat("yyyy-MM-dd");
    editor->setCalendarPopup(true);
    editor->installEventFilter(const_cast<DateDelegate*>(this));
    return editor;
}

void DateDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
    QString dateStr= index.model()->data(index).toString();
    QDate date = QDate::fromString(dateStr,Qt::ISODate);

    QDateTimeEdit *edit=static_cast<QDateTimeEdit*>(editor);
    edit->setDate(date);
}

void DateDelegate::setModelData(QWidget *editor,QAbstractItemModel *model, const QModelIndex &index) const
{
    QDateTimeEdit *edit=static_cast<QDateTimeEdit*>(editor);
    QDate date = edit->date();
    model->setData(index,QVariant(date.toString(Qt::ISODate)));
}

void DateDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}


//


#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);
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值