模型与视图简易示例

这个系统包括datasource、scoreinfo、scoreinfomodel和widget四个主要部分,实现了从文本文件中读取以逗号分隔的数据,如编号、名字和成绩,然后组织成数据项。数据项通过scoreinfomodel添加到模型中,并与QTableView视图关联。用户可以通过widget界面进行数据的加载、删除和右键删除操作。当右键点击视图时,会弹出上下文菜单供用户选择删除操作。
摘要由CSDN通过智能技术生成

 设计思路:

datasource.cpp:从文本文件中读取数据后进行解析(代码中以逗号为分隔符,将数据提取出来),并把数据送给scoreinfo.cpp进行处理,形成数据项,每一项数据项包含编号、名字、成绩

scoreinfo.cpp:组织数据,形成数据项,这里的数据项会传给scoreinfomodel.cpp

scoreinfomodel.cpp:将scoreinfo.cpp中的数据项添加到模型里面去,并将模型与视图相关联

widget.cpp:提供上层接口,控制模型与视图的显示,数据的加载与删除

文本文件中的数据:

//widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QStandardItemModel>
#include <QTreeView>
#include <QTableView>
#include <QListView>
#include <scoreinfomodel.h>
#include <QTableView>
#include <QPushButton>
#include <QMenu>

class Widget : public QWidget
{
    Q_OBJECT

    ScoreInfoModel m_model;
    QTableView m_view;
    QPushButton m_refreshBtn;
    QPushButton m_clearBtn;
    QMenu m_menu;
private slots:
    void refreshBtnClicked();
    void clearBtnClicked();
    void deleteActionClicked();
public:
    Widget(QWidget *parent = 0);
    bool eventFilter(QObject *watched, QEvent *event);

    ~Widget();
};

#endif // WIDGET_H
//scoreinfomodel.h

#ifndef SCOREINFOMODEL_H
#define SCOREINFOMODEL_H

#include <QObject>
#include <QStandardItemModel>
#include <scoreinfo.h>
#include <QTableView>
#include <QStandardItem>

class ScoreInfoModel : public QObject
{
    Q_OBJECT
    QStandardItemModel m_model;

public:
    explicit ScoreInfoModel(QObject *parent = nullptr);
    bool add(ScoreInfo info);
    void add(QList<ScoreInfo> list);
    bool remove(int i);
    ScoreInfo getItem(int i);
    int count();
    void setView(QTableView& view);
    void clear();

signals:

public slots:
};

#endif // SCOREINFOMODEL_H
//scoreinfo.h

#ifndef SCOREINFO_H
#define SCOREINFO_H

#include <QObject>
#include <QString>

class ScoreInfo : public QObject
{
    Q_OBJECT
    QString m_id;
    QString m_name;
    int m_score;
public:
    explicit ScoreInfo(QObject *parent = nullptr);
    explicit ScoreInfo(QString id, QString name, int score, QObject* parent = nullptr);
    ScoreInfo(const ScoreInfo& obj);
    ScoreInfo& operator= (const ScoreInfo& obj);
    QString getid();
    QString getname();
    int getscore();

signals:

public slots:
};

#endif // SCOREINFO_H
//datasource.h

#ifndef DATASOURCE_H
#define DATASOURCE_H

#include <QObject>
#include "scoreinfo.h"
#include <QList>

class DataSource : public QObject
{
    Q_OBJECT
    QList<ScoreInfo> m_data;
    bool parse(QString line, ScoreInfo& info);
public:
    explicit DataSource(QObject *parent = nullptr);
    bool setDataPath(QString path);
    QList<ScoreInfo> fetchData();
    int count();
signals:

public slots:
};

#endif // DATASOURCE_H

 

eventFilter(QObject *watched, QEvent *event)该函数用来安装事件过滤器,事件类型为QEvent::ContextMenu

查看帮助文档可知,当右击鼠标时,会发送QEvent::ContextMenu事件,接收处理后会弹出一个QMenu菜单

m_menu.exec(cursor().pos())用来弹出delete那个QMenu菜单

//widget.cpp

#include "widget.h"
#include <QStandardItem>
#include "datasource.h"
#include <QDebug>
#include "scoreinfomodel.h"
#include "scoreinfo.h"
#include <QMessageBox>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    m_view.installEventFilter(this);
    m_view.setParent(this);
    m_view.move(20,10);
    m_view.resize(300,200);

    m_refreshBtn.setText("刷新");
    m_refreshBtn.move(30, 220);
    m_refreshBtn.setParent(this);

    m_clearBtn.setText("删除");
    m_clearBtn.move(200, 220);
    m_clearBtn.setParent(this);

    m_menu.addAction("Delete");
    m_model.setView(m_view);

    connect(&m_refreshBtn, SIGNAL(clicked(bool)), this, SLOT(refreshBtnClicked()));
    connect(&m_clearBtn, SIGNAL(clicked(bool)), this, SLOT(clearBtnClicked()));
    connect(m_menu.actions()[0], SIGNAL(triggered(bool)), this, SLOT(deleteActionClicked()));

    refreshBtnClicked();

}

void Widget::refreshBtnClicked()
{
    DataSource ds;
    m_model.clear();

    if( ds.setDataPath("C:/Users/Administrator/Desktop/data/data.txt") )
    {
        m_model.add(ds.fetchData());
    }
    else
    {
        QMessageBox::critical(this, "error", "data source read error");
    }
}

void Widget::clearBtnClicked()
{
    m_model.clear();
}

void Widget::deleteActionClicked()
{
    m_model.remove(m_view.currentIndex().row());
}

bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if((watched == &m_view) && (event->type()== QEvent::ContextMenu))
    {
        m_menu.exec(cursor().pos());
    }

    return QWidget::eventFilter(watched, event);
}


Widget::~Widget()
{

}
//scoreinfomodel.cpp

#include "scoreinfomodel.h"
#include <QVariant>

ScoreInfoModel::ScoreInfoModel(QObject *parent) : QObject(parent)
{

}

void ScoreInfoModel::add(QList<ScoreInfo> list)
{
    for(int i=0; i<list.count(); i++)
    {
        add(list[i]);
    }
}

bool ScoreInfoModel::add(ScoreInfo info)
{
    bool ret = true;

    QStandardItem* root = m_model.invisibleRootItem();
    QStandardItem* item0 = new QStandardItem();
    QStandardItem* item1 = new QStandardItem();
    QStandardItem* item2 = new QStandardItem();

    if(m_model.rowCount() == 0)
    {
        QStringList list;

        list.append("ID");
        list.append("Name");
        list.append("Score");
        m_model.setHorizontalHeaderLabels(list);
    }

    if(root!=NULL && item0!=NULL && item1!=NULL && item2!=NULL)
    {
        item0->setData(info.getid(), Qt::DisplayRole);
        item1->setData(info.getname(), Qt::DisplayRole);
        item2->setData(info.getscore(), Qt::DisplayRole);

        item0->setEditable(false);
        item1->setEditable(false);
        item2->setEditable(false);

        int newRow = count();

        root->setChild(newRow, 0, item0);
        root->setChild(newRow, 1, item1);
        root->setChild(newRow, 2, item2);
    }
    else
    {
        ret = false;
    }

    return ret;

}



bool ScoreInfoModel::remove(int i)
{
    bool ret = true;

    if(i>=0 && i<count())
    {
        m_model.removeRow(i);
    }
    else
    {
        ret = false;
    }

    return ret;
}

ScoreInfo ScoreInfoModel::getItem(int i)
{
    ScoreInfo info;

    if(i>=0 && i<count())
    {
        QModelIndex index0 = m_model.index(i, 0, QModelIndex());
        QModelIndex index1 = m_model.index(i, 1, QModelIndex());
        QModelIndex index2 = m_model.index(i, 2, QModelIndex());

        QVariant v0 = index0.data();
        QVariant v1 = index1.data();
        QVariant v2 = index2.data();

        info = ScoreInfo(v0.toString(), v1.toString(), v2.toInt());
    }

    return info;
}

int ScoreInfoModel::count()
{
    return m_model.rowCount();
}

void ScoreInfoModel::setView(QTableView& view)
{
    view.setModel(&m_model);
}

void ScoreInfoModel::clear()
{
    m_model.clear();
}
//scoreinfo.cpp

#include "scoreinfo.h"

ScoreInfo::ScoreInfo(QObject *parent) : QObject(parent)
{
    m_id = "NULL";
    m_name = "NULL";
    m_score = -1;
}

ScoreInfo::ScoreInfo(QString id, QString name, int score, QObject *parent)
{
    m_id = id;
    m_name = name;
    m_score = score;
}

ScoreInfo::ScoreInfo(const ScoreInfo &obj)
{
        m_id = obj.m_id;
        m_name = obj.m_name;
        m_score = obj.m_score;
}

ScoreInfo& ScoreInfo::operator= (const ScoreInfo& obj)
{
    if(this != &obj)
    {
        m_id = obj.m_id;
        m_name = obj.m_name;
        m_score = obj.m_score;
    }

    return *this;
}

QString ScoreInfo::getid()
{
    return m_id;
}

QString ScoreInfo::getname()
{
    return m_name;
}

int ScoreInfo::getscore()
{
    return m_score;
}
//datasource.cpp

#include "datasource.h"
#include <QFile>
#include <QTextStream>
#include <QStringList>
#include <QDebug>

DataSource::DataSource(QObject *parent) : QObject(parent)
{

}

bool DataSource::parse(QString line, ScoreInfo& info)
{
    bool ret = true;
        QStringList list = line.split(",", QString::SkipEmptyParts);

        if( list.count() == 3 )
        {
            QString id = list[0].trimmed();
            QString name = list[1].trimmed();
            QString score = list[2].trimmed();
            int value = score.toInt(&ret);

            if( ret && (0 <= value) && (value <=150) )
            {
                info = ScoreInfo(id, name, value);
            }
            else
            {
                ret = false;
            }
        }
        else
        {
            ret = false;
        }

        return ret;
}

bool DataSource::setDataPath(QString path)
{
    bool ret = true;
        QFile file(path);

        if( file.open(QIODevice::ReadOnly | QIODevice::Text) )
        {
            QTextStream in(&file);

            while( !in.atEnd() )
            {
                ScoreInfo info;

                if( parse(in.readLine(), info) )
                {
                    m_data.append(info);
                }
            }

            file.close();
        }
        else
        {
            ret = false;
        }

        return ret;
}

QList<ScoreInfo> DataSource::fetchData()
{
    QList<ScoreInfo> ret = m_data;
    m_data.clear();
    return ret;
}

int DataSource::count()
{
    return m_data.count();
}
//main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.resize(350,300);
    w.show();

    return a.exec();
}

演示:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值