设计思路:
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();
}
演示: