Qt官方示例:BarModelMapper Example(条形图数据模型映射)

这个示例的内容主要有两个知识点:

  • 自定义数据模型的方法。
  • 条形图的数据模型映射器 QVBarModelMapper 类的用法。

自定义数据模型:使用随机数据作为模型的数据:

#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 = nullptr);
    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
#include "customtablemodel.h"
#include <QtCore/QVector>
#include <QtCore/QTime>
#include <QtCore/QRect>
#include <QtCore/QRandomGenerator>
#include <QtGui/QColor>

CustomTableModel::CustomTableModel(QObject *parent) :
    QAbstractTableModel(parent)
{
    m_columnCount = 6;
    m_rowCount = 12;

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

int CustomTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_data.count();
}

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

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

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

        return QColor(Qt::white);// 未映射的单元格返回白色
    }
    return QVariant();
}

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

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

关于自定义模型,还可以参考:自定义模型

上面这个模型唯一的特别之处在于:默认是白色背景,在一些特别位置数据的背景色是设置的其他颜色。

主界面:

#include "tablewidget.h"
#include "customtablemodel.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>
#include <QDebug>

QT_CHARTS_USE_NAMESPACE

TableWidget::TableWidget(QWidget *parent)
    : QWidget(parent)
{
    m_model = new CustomTableModel;

    QTableView *tableView = new QTableView;
    tableView->setModel(m_model);
    tableView->setMinimumWidth(400);
    tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    m_model->setParent(tableView);

    QBarSeries *series = new QBarSeries;//条形图

    int first = 3;
    QVBarModelMapper *mapper = new QVBarModelMapper(this);
    mapper->setFirstBarSetColumn(1);//条形集的数据源的模型列,第一列开始,共4列
    mapper->setLastBarSetColumn(4);    
    mapper->setFirstRow(first);//第3行开始,共5行
    mapper->setRowCount(5);
    mapper->setSeries(series);
    mapper->setModel(m_model);

    QChart *chart = new QChart;
    chart->setAnimationOptions(QChart::AllAnimations);
    chart->addSeries(series);

    //获取条形图的颜色并将其用于显示映射区域
    QList<QBarSet *> barsets = series->barSets();//4
    for (int i = 0; i < barsets.count(); ++i)
    {
        QBarSet * bar = barsets.at(i);
        QString seriesColorHex = "#" + QString::number(bar->brush().color().rgb(),16).right(6).toUpper();
        QRect rect = QRect(1 + i, first, 1, bar->count());//bar->count() = 5
        m_model->addMapping(seriesColorHex, rect);
        qDebug()<<seriesColorHex<<" "<<rect;
    }

    QBarCategoryAxis *axisX = new QBarCategoryAxis();//条形图坐标轴
    axisX->append(QStringList() << "四月" << "五月" << "六月" << "七月" << "八月");
    chart->addAxis(axisX, Qt::AlignBottom);
    series->attachAxis(axisX);

    QValueAxis *axisY = new QValueAxis();
    chart->addAxis(axisY, Qt::AlignLeft);
    series->attachAxis(axisY);

    QChartView *chartView = new QChartView(chart);
    chartView->setRenderHint(QPainter::Antialiasing);
    chartView->setMinimumSize(640, 480);

    QGridLayout *mainLayout = new QGridLayout;
    mainLayout->addWidget(tableView, 1, 0);
    mainLayout->addWidget(chartView, 1, 1);
    mainLayout->setColumnStretch(1, 1);
    mainLayout->setColumnStretch(0, 0);
    setLayout(mainLayout);
}

可见模型的列名称被用作图表的图例。

改变模型中的数据图表跟着变化。

反过来,用一个定时器定时改变图表中的数据:

    QTimer * timer = new QTimer(this);
    connect(timer,&QTimer::timeout,this,[series]()mutable
    {
        QBarSet * bar = series->barSets()[0];
        bar->replace(2,QRandomGenerator::global()->bounded(300));
    });
    timer->start(1000);

模型中的数据也会同步变化。 

示例中的一个小技巧,颜色转16进制字符串:

QColor color;
QString seriesColorHex = "#" + QString::number(color.rgb(),16).right(6).toUpper();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值