QTChart实现柱状图的mvc模型

QT MVC模型

QT MVC(Model-View-Controller)模型是QT框架的一种设计模式,用于实现应用程序的分层结构和分离关注点。MVC模型将应用程序分为三个部分:模型(Model)、视图(View)和控制器(Controller)。

  • 模型(Model):模型是应用程序的数据和业务逻辑部分。它负责存储应用程序的数据和定义操作数据的方法。模型是不依赖于视图的的部分,它应该是一个独立的的数据结构和算法集合。
  • 视图(View):视图是应用程序的UI部分,它负责展示模型中的数据和呈现用户界面。视图可以直接访问模型,但是它应该只读取模型中的数据而不应该修改模型。视图应该能够动态地反映出模型的变化。
  • 控制器(Controller):控制器是应用程序的事件处理部分,它负责处理用户输入并更新模型。控制器监听用户输入设备(如鼠标、键盘等)的事件,并根据事件类型更新模型。控制器应该是一个被动部分,它不应该直接修改模型或视图,而是通过信号和槽机制来实现。

在MVC模型中,模型、视图和控制器之间通过信号和槽机制进行通信。模型发出数据变化信号,视图通过槽函数监听该信号并更新视图。同样地,控制器也通过信号和槽机制监听用户输入事件并更新模型。通过MVC模型,应用程序实现了数据、业务逻辑和UI的分离,提高了代码的可维护性和可扩展性。

举例代码

CustomTableModel.hpp

#ifndef CUSTOMTABLEMODEL_H
#define CUSTOMTABLEMODEL_H

#include <QtCore/QAbstractTableModel>
#include <QtCore/QHash>
#include <QtCore/QRect>

class CustomTableModel : public QAbstractTableModel
{
    
    
    Q_OBJECT
public:
    explicit CustomTableModel(QObject *parent = 0);
    virtual ~CustomTableModel();

    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    int columnCount(const QModelIndex &parent = QModelIndex()) const;
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
    Qt::ItemFlags flags(const QModelIndex &index) const;

    void addMapping(QString color, QRect area);
    void clearMapping() {
    
     m_mapping.clear(); }

private:
    QList<QVector<qreal> * > m_data;
    QHash<QString, QRect> m_mapping;
    int m_columnCount;
    int m_rowCount;
};

#endif // CUSTOMTABLEMODEL_H

CustomTableModel.cpp代码:

#include "customtablemodel.h"
#include <QtCore/QVector>
#include <QtCore/QTime>
#include <QtCore/QRect>
#include <QtCore/QRandomGenerator>
#include <QtGui/QColor>

/**
 * @brief CustomTableModel::CustomTableModel  抽象的数据模型
 * @param parent
 */
CustomTableModel::CustomTableModel(QObject *parent) :
    QAbstractTableModel(parent)
{
    
    
    m_columnCount = 6;
    m_rowCount = 12;

    // m_data
    for (int i = 0; i < m_rowCount; i++) {
    
    
        QVector<qreal>* dataVec = new QVector<qreal>(m_columnCount);
        for (int k = 0; k < dataVec->size(); k++) {
    
    
            if (k % 2 == 0)
                dataVec->replace(k, i * 50 + QRandomGenerator::global()->bounded(20));
            else
                dataVec->replace(k, QRandomGenerator::global()->bounded(100));
        }
        m_data.append(dataVec);
    }
}

CustomTableModel::~CustomTableModel()
{
    
    
    qDeleteAll(m_data);
}


/**
 * @brief CustomTableModel::rowCount 获取数据行数
 * @param parent
 * @return
 */
int CustomTableModel::rowCount(const QModelIndex &parent) const
{
    
    
    Q_UNUSED(parent)
    return m_data.count();
}

/**
 * @brief CustomTableModel::columnCount  数据列数
 * @param parent
 * @return
 */

int CustomTableModel::columnCount(const QModelIndex &parent) const
{
    
    
    Q_UNUSED(parent)
    return m_columnCount;
}

/**
 * @brief CustomTableModel::headerData 数据的表头信息
 * @param section
 * @param orientation
 * @param role
 * @return
 */
QVariant CustomTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    
    
    if (role != Qt::DisplayRole)
        return QVariant();

    if (orientation == Qt::Horizontal)
        return QString("201%1").arg(section);
    else
        return QString("%1").arg(section + 1);
}

/**
 * @brief CustomTableModel::data  数据信息
 * @param index
 * @param role
 * @return
 */
QVariant CustomTableModel::data(const QModelIndex &index, int role) const
{
    
    
    if (role == Qt::DisplayRole) {
    
    
        return m_data[index.row()]->at(index.column());
    } else if (role == Qt::EditRole) {
    
    
        return m_data[index.row()]->at(index.column());
    } else if (role == Qt::BackgroundRole) {
    
    
        for (const QRect &rect : m_mapping) {
    
    
            if (rect.contains(index.column(), index.row()))
                return QColor(m_mapping.key(rect));
        }

        // cell not mapped return white color
        return QColor(Qt::white);

    }
    return QVariant();
}

/**
 * @brief CustomTableModel::setData 数据可以修改的
 * @param index
 * @param value
 * @param role
 * @return
 */
bool CustomTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    
    
    if (index.isValid() && role == Qt::EditRole) {
    
    
        m_data[index.row()]->replace(index.column(), value.toDouble());
        emit dataChanged(index, index);
        return true;
    }
    return false;
}


/**
 * @brief CustomTableModel::flags 设置状态标识
 * @param index
 * @return
 */
Qt::ItemFlags CustomTableModel::flags(const QModelIndex &index) const
{
    
    
    return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}

void CustomTableModel::addMapping(QString color, QRect area)
{
    
    
    m_mapping.insertMulti(color, area);
}

tablewiget代码如下:

#include "tablewidget.h"
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QTableView>
#include <QtCharts/QChart>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
#include <QtCharts/QVXYModelMapper>
#include <QtCharts/QBarSeries>
#include <QtCharts/QBarSet>
#include <QtCharts/QVBarModelMapper>
#include <QtWidgets/QHeaderView>
#include <QtCharts/QBarCategoryAxis>
#include <QtCharts/QValueAxis>

QT_CHARTS_USE_NAMESPACE

TableWidget::TableWidget(QWidget *parent)
    : QWidget(parent)
{
    
    
    // create simple model for storing data
    // user's table data model
    //! [1]
    m_model = new CustomTableModel;
    //! [1]

    //! [2]
    // create table view and add model to it
    QTableView *tableView = new QTableView;
    tableView->setModel(m_model);
    tableView->setMinimumWidth(300);
    tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    m_model->setParent(tableView);
    //! [2]

    //! [3]
    QChart *chart = new QChart;
    chart->setAnimationOptions(QChart::AllAnimations);
    //! [3]

    // series 1
    //! [4]
    QBarSeries *series = new QBarSeries;

    int first = 1;
    int count = 6;
    QVBarModelMapper *mapper = new QVBarModelMapper(this);
    mapper->setFirstBarSetColumn(0);
    mapper->setLastBarSetColumn(5);
    mapper->setFirstRow(first);
    mapper->setRowCount(count);
    mapper->setSeries(series);
    mapper->setModel(m_model);
    chart->addSeries(series);
    //! [4]

    //! [5]
    // for storing color hex from the series
    QString seriesColorHex = "#000000";

    // get the color of the series and use it for showing the mapped area
    QList<QBarSet *> barsets = series->barSets();
    for (int i = 0; i < barsets.count(); i++) {
    
    
        seriesColorHex = "#" + QString::number(barsets.at(i)->brush().color().rgb(), 16).right(6).toUpper();
        m_model->addMapping(seriesColorHex, QRect( i, first, 1, barsets.at(i)->count()));
    }
    //! [5]

    //! [6]
    QStringList categories;
    categories << "April" << "May" << "June" << "July" << "August" <<"surptember";
    QBarCategoryAxis *axisX = new QBarCategoryAxis();
    axisX->append(categories);
    chart->addAxis(axisX, Qt::AlignBottom);
    series->attachAxis(axisX);
    QValueAxis *axisY = new QValueAxis();
    chart->addAxis(axisY, Qt::AlignLeft);
    series->attachAxis(axisY);
    //! [6]

    //! [7]
    QChartView *chartView = new QChartView(chart);
    chartView->setRenderHint(QPainter::Antialiasing);
    chartView->setMinimumSize(640, 480);
    //! [7]

    //! [8]
    // create main layout
    QGridLayout *mainLayout = new QGridLayout;
    mainLayout->addWidget(tableView, 1, 0);
    mainLayout->addWidget(chartView, 1, 1);
    mainLayout->setColumnStretch(1, 1);
    mainLayout->setColumnStretch(0, 0);
    setLayout(mainLayout);
    //! [8]
}

main.cpp如下:

#include <QtWidgets/QApplication>
#include "tablewidget.h"

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

    QApplication a(argc, argv);
    TableWidget w;
    w.show();
    return a.exec();
}

实际运行效果图:

在这里插入图片描述

总结

在实际项目中会经常用到类似的数据模型,非常方便使用的。

猜你喜欢

转载自blog.csdn.net/u011046042/article/details/132011571