自定义模型类

QStandardItemModel 是一个通用的模型类

能够以任意的方式组织数据

数据组织的基本单位为数据项 (QStandardItem)

每一个数据项能够存储多个具体数据 (附加数据角色)

每一个数据项能够对数据状态进行控制 (可编辑,可选,...)

Qt 中通用的模型类 QStandardItemModel

Qt 中的变体类型 QVariant

QVariant 是一个用于封装的类型

QVariant 能够表示大多数常见的值类型

QVariant 每次只能封装 (保存) 单一类型的值

QVariant 的意义在于能够设计 "返回类型可变的函数"

变体类型 QVariant 中的常用成员函数

变体类型 QVariant 的应用

#include <QCoreApplication>
#include <QVariant>
#include <QPoint>
#include <QDebug>

QVariant func()
{
    QVariant v(10);

    return v;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QVariant v1(1);
    QVariant v2(3.14);
    QVariant v3("520");
    QVariant v4(QPoint(3, 4));
    QVariant v5;

    qDebug() << v1.type();
    qDebug() << v1.typeName();
    qDebug() << v1.toInt();
    qDebug() << v1.value<int>();

    qDebug() << endl;

    qDebug() << v2.type();
    qDebug() << v2.typeName();
    qDebug() << v2.toInt();
    qDebug() << v2.toDouble();
    qDebug() << v2.value<double>();

    qDebug() << endl;

    qDebug() << v3.type();
    qDebug() << v3.typeName();
    qDebug() << v3.toInt();
    qDebug() << v3.value<QString>();

    qDebug() << endl;

    bool ok = true;
    qDebug() << v4.type();
    qDebug() << v4.typeName();
    qDebug() << v4.toPoint();
    qDebug() << v4.value<QPoint>();
    qDebug() << v4.toInt(&ok);
    qDebug() << ok;

    qDebug() << endl;
    qDebug() << v5.isValid();

    return a.exec();
}

程序运行结果如下所示:

工程中的常用模型设计

解析数据源中的数据 (数据库,网络,串口,等)

将解析后的数据存入 QStandardItem 对象中

根据数据间的关系在 QStandardItemModel 对象中组织数据项

选择合适的视图显示数据值

实例分析:

在文件中以行的形式存储了考试存储信息 (ID,Name,Score)

开发 GUI 程序显示文件中的信息

  • 计算平均成绩
  • 查找最好成绩和最差成绩
  • 可刷新显示的内容和删除内容

系统框架图

系统核心类图

系统架构图

DataSource 类的设计与实现

设置数据源并读取数据

对数据进行解析后生产数据对象

ScoreInfo 类的设计与实现

封装数据源中的一组完整数据

提供返回具体数值的接口函数

ScoreInfoModel 类的设计与实现

使用标准模型类 QStandardItemModel 作为成员

以 ScoreInfo 类对象为最小单位进行数据组织

数据交互流程图

界面设计

右键上下文菜单的实现

定义菜单对象 (QMenu)

连接菜单中的 QAction 对象到槽函数

定义事件过滤器,并处理 ContextMenu 事件

在当前鼠标的位置打开菜单对象

编程实验

DataSource.h

#ifndef DATASOURCE_H
#define DATASOURCE_H

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

class DataSource : public QObject
{
    Q_OBJECT
private:
    QList<ScoreInfo> m_data;

    bool parse(QString line, ScoreInfo &obj);

public:
    explicit DataSource(QObject* parent = nullptr);

    bool setDataPath(const QString path);
    QList<ScoreInfo> fetchData();
    int count() const;
};

#endif // DATASOURCE_H

DataSource.cpp

#include "DataSource.h"
#include <QFile>
#include <QTextStream>

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

}

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

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

        if((ret) && (score >= 0) && (score <= 150))
        {
            obj = ScoreInfo(id, name, score);
        }
        else
        {
            ret = false;
        }
    }
    else
    {
        ret = false;
    }
    return ret;
}

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

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

        while(!in.atEnd())
        {
            QString line = in.readLine();
            ScoreInfo info;

            if(parse(line, 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() const
{
    return m_data.count();
}

ScoreInfo.h

#ifndef SCOREINFO_H
#define SCOREINFO_H

#include <QObject>

class ScoreInfo : public QObject
{
    Q_OBJECT
private:
    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 id();
    QString name();
    int score();

};

#endif // SCOREINFO_H

ScoreInfo.cpp

#include "ScoreInfo.h"

ScoreInfo::ScoreInfo(QObject *parent) : QObject(parent)
{

}

ScoreInfo::ScoreInfo(QString id, QString name, int score, QObject* parent) : 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::id()
{
    return m_id;
}

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

int ScoreInfo::score()
{
    return m_score;
}

ScoreInfoModel.h

#ifndef SCOREINFOMODEL_H
#define SCOREINFOMODEL_H

#include <QObject>
#include <QStandardItemModel>
#include <QTableView>
#include "ScoreInfo.h"


class ScoreInfoModel
{
private:
    QStandardItemModel m_model;

public:
    ScoreInfoModel();

    bool add(ScoreInfo obj);
    void add(QList<ScoreInfo> obj);
    bool remove(int i);
    ScoreInfo getItem(int i);
    int count();
    void clear();
    void setView(QTableView& view);
};

#endif // SCOREINFOMODEL_H

ScoreInfoModel.cpp

#include "ScoreInfoModel.h"
#include <QStandardItem>
#include <QModelIndex>
#include <QVariant>

ScoreInfoModel::ScoreInfoModel()
{

}

bool ScoreInfoModel::add(ScoreInfo obj)
{
    bool ret = true;
    QStandardItem *root = m_model.invisibleRootItem();
    QStandardItem *item0 = new QStandardItem();
    QStandardItem *item1 = new QStandardItem();
    QStandardItem *item2 = new QStandardItem();;

    if(count() == 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(obj.id(), Qt::DisplayRole);
        item1->setData(obj.name(), Qt::DisplayRole);
        item2->setData(obj.score(), 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;
}

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

bool ScoreInfoModel::remove(int i)
{
    bool ret = ((i >= 0) && (i < count()));

    if(ret)
    {
        m_model.removeRows(i, 1);
    }

    return ret;
}

ScoreInfo ScoreInfoModel::getItem(int i)
{
    ScoreInfo info;
    bool ret = ((i >= 0) && (i < count()));

    if(ret)
    {
        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(Qt::DisplayRole);
        QVariant v1 = index1.data(Qt::DisplayRole);
        QVariant v2 = index2.data(Qt::DisplayRole);

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

    return info;
}

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

void ScoreInfoModel::clear()
{
    m_model.clear();
}

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

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTableView>
#include <QPushButton>
#include <QMenu>
#include "ScoreInfoModel.h"

class Widget : public QWidget
{
    Q_OBJECT
private:
    ScoreInfoModel m_model;
    QTableView m_view;
    QMenu m_menu;
    QPushButton m_refreshBtn;
    QPushButton m_clearBtn;
    QPushButton m_scoreBtn;

private slots:
    void onRefreshBtnClicked();
    void onClearBtnClicked();
    void onScoreBtnClicked();
    void onDeleteActionClicked();

public:
    Widget(QWidget* parent = nullptr);
    bool eventFilter(QObject* obj, QEvent* e);
    ~Widget();
};
#endif // WIDGET_H

Widget.cpp

#include "Widget.h"
#include "DataSource.h"
#include "ScoreInfo.h"
#include "ScoreInfoModel.h"
#include <QDebug>
#include <QMessageBox>

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

    m_refreshBtn.setParent(this);
    m_refreshBtn.move(10, 320);
    m_refreshBtn.resize(100, 30);
    m_refreshBtn.setText("Refresh");

    m_clearBtn.setParent(this);
    m_clearBtn.move(150, 320);
    m_clearBtn.resize(100, 30);
    m_clearBtn.setText("Clear");

    m_scoreBtn.setParent(this);
    m_scoreBtn.move(290, 320);
    m_scoreBtn.resize(100, 30);
    m_scoreBtn.setText("Score");

    m_menu.addAction("Delete");

    connect(m_menu.actions()[0], &QAction::triggered, this, &Widget::onDeleteActionClicked);
    connect(&m_refreshBtn, &QPushButton::clicked, this, &Widget::onRefreshBtnClicked);
    connect(&m_clearBtn, &QPushButton::clicked, this, &Widget::onClearBtnClicked);
    connect(&m_scoreBtn, &QPushButton::clicked, this, &Widget::onScoreBtnClicked);

    m_model.setView(m_view);

    onRefreshBtnClicked();
}

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

void Widget::onRefreshBtnClicked()
{
    m_model.clear();

    DataSource ds;

    if(ds.setDataPath("C:/Users/Administrator/Desktop/test.txt"))
    {
        m_model.add(ds.fetchData());
    }
    else
    {
        QMessageBox::critical(this, "error", "Open file error", QMessageBox::Ok);
    }
}

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

void Widget::onScoreBtnClicked()
{
    int max = 0;
    int min = 250;
    int avarage = 0;

    if(m_model.count() != 0)
    {
        for(int i = 0; i < m_model.count(); i++)
        {
            ScoreInfo info;

            info = m_model.getItem(i);

            if(max < info.score())
            {
                max = info.score();
            }
            if(min > info.score())
            {
                min = info.score();
            }

            avarage += info.score();
        }

        avarage /= m_model.count();

        QMessageBox::information(this, "information", QString().sprintf("Max : %d\nMin : %d\nAvarage : %d", max, min, avarage), QMessageBox::Ok);
    }
    else
    {
        QMessageBox::information(this, "information", "No data recorded", QMessageBox::Ok);
    }
}

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

    return QWidget::eventFilter(obj, e);
}

Widget::~Widget()
{
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Python中,我们可以使用`Pipeline`自定义模型来构建机器学习流水线。流水线是一个将多个机器学习步骤串联起来的方法,可以方便地组合多个处理步骤,例如特征提取、特征选择、模型训练等。 首先,我们需要导入需要的库和模块,例如`Pipeline`和其他所需的预处理工具、模型等。然后,我们可以定义一个自定义模型,该继承自`BaseEstimator`和`TransformerMixin`。 在自定义模型中,我们需要定义两个方法:`fit`和`transform`。`fit`方法用于训练模型,接受输入的数据和标签,并根据需要进行模型训练。`transform`方法则用于对输入的数据进行转换,例如特征提取、特征选择等操作。 在模型中,可以使用其他库、模块或函数来实现特定的功能。例如,在`fit`方法中,我们可以使用`scikit-learn`或其他机器学习库中的算法来进行模型训练。在`transform`方法中,我们可以使用其他预处理工具来进行特征提取或特征选择。 最后,我们可以使用`Pipeline`来将多个处理步骤连接在一起,形成一个完整的机器学习流水线。通过`Pipeline`,我们可以指定自定义模型、预处理工具和其他步骤的顺序,并且方便地对数据进行处理和模型训练。 总结起来,通过自定义模型和使用`Pipeline`,我们可以在Python中灵活地构建机器学习流水线,实现数据处理和模型训练等多个步骤的串联,并且方便地重复使用和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值