我的Qt QAbstractProxyModel崩溃与图表视图,但不与表视图

My Qt QAbstractProxyModel crashes with ChartView but not with TableView?

本文关键字:视图 Qt QAbstractProxyModel 崩溃 我的      更新时间:2023-10-16

我有一个自定义的QAbstractTableModel和一个代理模型,它翻转第一个模型的轴。对于这个表,我只需要切换模型。当我切换到图表的代理模型时,当我将行分配给QHXYModelMapper时,它崩溃了。我搞砸了什么?

这是表模型:

#include "tablemodel.h"
TableModel::TableModel(QObject *parent) :
    QAbstractTableModel(parent)
{
}
int TableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_data.count();
}
int TableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    if(m_data.count() < 1)
    {
        return 0;
    }
    return m_data[0].count();
}
QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();
    if (orientation == Qt::Horizontal) {
        if (section % 2 == 0)
            return "x";
        else
            return "y";
    } else {
        return QString("%1").arg(section + 1);
    }
}
QVariant TableModel::data(const QModelIndex &index, int role) const
{
    if (!role == Qt::DisplayRole)
    {
        return QVariant();
    }
    return m_data[index.row()].at(index.column());
}
bool TableModel::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;
}
void TableModel::appendRow(QVector<double> row)
{
    emit layoutAboutToBeChanged();
    emit beginInsertRows(QModelIndex(), rowCount(), rowCount());
    m_data.append(row);
    emit endInsertRows();
    emit layoutChanged();
}
void TableModel::clear()
{
    for(int i = 0; i < m_data.count(); ++i)
    {
        m_data[i].clear();
    }
    m_data.clear();
}

这是代理实现:

HorizontalProxyModel::HorizontalProxyModel(QObject *parent) : QAbstractProxyModel(parent)
{
}
QModelIndex HorizontalProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
    if (sourceModel()) {
        return sourceModel()->index(proxyIndex.column(), proxyIndex.row());
    } else {
        return QModelIndex();
    }
}
QModelIndex HorizontalProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
    return index(sourceIndex.column(), sourceIndex.row());
}
QModelIndex HorizontalProxyModel::index(int row, int column, const QModelIndex &) const
{
    return createIndex(row, column, (void*) 0);
}
QModelIndex HorizontalProxyModel::parent(const QModelIndex &) const
{
    return QModelIndex();
}
int HorizontalProxyModel::rowCount(const QModelIndex &) const
{
    return sourceModel() ? sourceModel()->columnCount() : 0;
}
int HorizontalProxyModel::columnCount(const QModelIndex &) const
{
    return sourceModel() ? sourceModel()->rowCount() : 0;
}
QVariant HorizontalProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (!sourceModel()) { return QVariant(); }
    Qt::Orientation new_orientation = orientation == Qt::Horizontal ?
                Qt::Vertical : Qt::Horizontal;
    return sourceModel() ? sourceModel()->headerData(section, new_orientation, role) : 0;
}
QVariant HorizontalProxyModel::data(const QModelIndex &index) const
{
    qDebug() << "h model data";
    return sourceModel() ? sourceModel()->data(sourceModel()->index(index.column(), index.row())) : 0;
}

这是我分配模型的地方:

void MainWindow::plot(QAbstractItemModel* m)
{
QChart* chart = new QChart;
qDebug() << m->rowCount() << " " << m->columnCount();
for(int row = 0; row < m->rowCount(); ++row)
{
    QLineSeries *series = new QLineSeries;
    QHXYModelMapper* mapper = new QHXYModelMapper;
    QString name = "Row " + QString::number(row);
    series->setName(name);
    mapper->setModel(m);
    mapper->setSeries(series);
    mapper->setXRow(row);  //crashes here if proxy model
    mapper->setYRow(row);
    chart->addSeries(series);
}
chart->createDefaultAxes();
QChart* oldChart = chartView->chart();
chartView->setChart(chart);
oldChart->deleteLater();
}

编辑

Some more info…

查看调试器,似乎在ProxyModel中创建的索引并传递给原始模型是-1/-1(无效)。这个调试输出中的第9行是否意味着正在调用基类QAbstractProxyModel::data(),而不是来自派生代理模型的基类?如果是,为什么?

1   __pthread_kill                                                                                 
    0x7fff91eaff06 
2   pthread_kill                                                                                       0x7fff907204ec 
3   abort                                                                                              0x7fff876cd6df 
4   qt_message_fatal(QtMsgType, QMessageLogContext const&, QString const&)                             0x100ac3e79    
5   QMessageLogger::fatal(const char *, ...) const                                                     0x100ac5847    
6   qt_assert_x(const char *, const char *, const char *, int)                                         0x100ac0682    
7   QList<QVector<double>>::operator[](int) const                               qlist.h            541 0x10000fced    
8   TableModel::data(QModelIndex const&, int) const                             tablemodel.cpp     46  0x10000f8f1    
9   QAbstractProxyModel::data(QModelIndex const&, int) const                                           0x100c4c28b    
10  QtCharts::QXYModelMapperPrivate::valueFromModel(QModelIndex)                                       0x10171dfb3    
11  QtCharts::QXYModelMapperPrivate::initializeXYFromModel()                                           0x10171d92f    
12  QtCharts::QHXYModelMapper::setYRow(int)                                                            0x101720bf4    
13  MainWindow::plot(QAbstractItemModel *)

UDPATE:修复

所以,我现在的修复是手动调用QHXYModelMapper::setColumnCount(),像这样:

mapper->setModel(m);
mapper->setSeries(series);
mapper->setColumnCount(m->columnCount());
mapper->setXRow(row);
mapper->setYRow(row);

文档似乎暗示默认值将使用模型中的总列数,如果我不显式设置这个:

http://doc.qt.io/qt-5/qhxymodelmapper.html columnCount-prop

在Qt论坛上讨论了一下,这似乎是一个错误,其中HXYModelMapper columnCount属性的默认值实际上并没有从模型中检索适当的columnCount。解决方法是自己调用setColumnCount并将其设置为模型的columnCount

mapper->setModel(m);
mapper->setSeries(series);
mapper->setColumnCount(m->columnCount());
mapper->setXRow(row);
mapper->setYRow(row);

Bug报告:https://bugreports.qt.io/browse/QTBUG-57342