当底层qmap更新时,c++qtqabstractablemodel子类chrash

c++ qt qabstracttablemodel subclass chrashes when underlying qmap is updated

本文关键字:c++qtqabstractablemodel 子类 chrash 更新 qmap      更新时间:2023-10-16

我在更新自定义qabstracttablemodel时遇到了很大的麻烦。我想要一张能显示几种股票价格的表格。我从我控制的本地服务器上获取价格。此设置用于测试目的。在工作者线程中接收定价信息。

我已经用以下方式对qabstractablemodel进行了子类化:

价格模型.h:

class PriceModel : public QAbstractTableModel {
    Q_OBJECT
public:
    PriceModel( QObject* parent = 0 );
    void setPriceMap( const QMap<QString, ITick*> &curTickMap );
    int rowCount( const QModelIndex &parent ) const;
    int columnCount( const QModelIndex &parent ) const;
    QVariant data( const QModelIndex &index, int role ) const;
    QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
private:
    QMap<QString, ITick*> currentTicks;
    QString stockAt( int offset ) const;
};

价格模型.cpp

#include "PriceModel.h"
PriceModel::PriceModel( QObject* parent ) : QAbstractTableModel( parent ) {
}
int PriceModel::rowCount( const QModelIndex& parent ) const {
    return this->currentTicks.count();
}
int PriceModel::columnCount( const QModelIndex& parent ) const {
    return 4;
}
QString PriceModel::stockAt( int offset ) const {
    return ( currentTicks.begin() + offset ).key();
}
QVariant PriceModel::data( const QModelIndex& index, int role ) const {
    if ( !index.isValid() ) {
        return QVariant();
    }
    if ( role == Qt::TextAlignmentRole ) {
        return int( Qt::AlignRight | Qt::AlignVCenter );
    } else if ( role == Qt::DisplayRole ) {
        QString stock = stockAt( index.row() );
        int i = index.column();
        switch ( i ) {
            case 0 : return currentTicks.value( instrument )->getTime().toString( "hh:mm:ss:zzz" );
            case 1 : return currentTicks.value( instrument )->getBid();
            case 2 : return currentTicks.value( instrument )->getAsk();
            case 3 : return currentTicks.value( instrument )->getBidVolume();
            case 4 : return currentTicks.value( instrument )->getAskVolume();
        }
    }
    return QVariant();
}
QVariant PriceModel::headerData( int section, Qt::Orientation orientation, int role )  const {
    if ( role != Qt::DisplayRole ) {
        return QVariant();
    }
    if ( orientation == Qt::Horizontal ) {
        switch ( section ) {
            case 0 : return QString( "Time" );
            case 1 : return QString( "Bid" );
            case 2 : return QString( "Ask" );
            case 3 : return QString( "Bid Volume" );
            case 4 : return QString( "Ask Volume" );
        }
    } else {
        return instrumentAt( section )->getCurrencyPairWithDelimiter();
    }
    return QVariant();
}
void PriceModel::setTickMap( const QMap<QString,ITick*>& curTickMap ) {
    beginResetModel();
    this->currentTicks = curTickMap;
    endResetModel();
}

当我调用setTickMap(qmap<…>)方法时,模型会填充表视图,并且所有不同的股票都会按预期显示。(初始化我的模型中的数据运行良好)

当我想再次调用setTickMap(qmap<…>)方法时,问题就出现了。应用程序崩溃,我不明白为什么,也没有收到一条重要的错误消息,即segvault。

在调试配置崩溃时,netbeans打开一个名为"Disassemblyby"的选项卡,其中包含以下内容:

QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+50: add    %ebx,%r15d
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+85: testb $0x4,0x20(%rax)
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+89: jne 0x7ffff63f4df8 <QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+536>
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+102: add    0x6c(%rsp),%ebx
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+118: mov    %ebx,0x2c(%rsp)
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+106: movq   $0x0,0x40(%rsp)
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+95: mov    0x31c19a(%rip),%rdx        # 0x7ffff6710de0
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+115: mov    (%rdx),%rax
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+122: test   %rax,%rax
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+125: je     0x7ffff63f4c72 <QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+146>
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+127: lea    0x40(%rsp),%rdx
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+132: test   %r13,%r13
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+135: mov    %ebx,%esi
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+137: mov    %r12,%rdi
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+140: cmovne %r13,%rdx
QMetaObject::activate(QObject*, QMetaObject const*, int, void**)+144: callq  *%rax

我将映射赋值夹在beginResetModel()方法中,但这似乎不起作用,因为我只是得到了一个崩溃的应用程序。这在setter方法的第一次调用时就足够了。这让我认为这是一个非常愚蠢的错误。我认为,由于第一个调用运行良好,我们可以排除它与线程间通信问题有关。

这个模型不应该由用户通过GUI编辑,我知道我本可以使用tablewidget来显示数据,但我不确定是否会有另一个视图共享这个模型信息。当前价格的地图不会很大(最多25件商品),所以我对每一个新价格都重置模型并不感到不舒服。

提前谢谢,我希望有人能帮我微孔

考虑到您正在显示实时tickdata,我建议您接近数据存储。由于你只显示了勾号中的5个项目,你可能想考虑其他项目,那么QMap可能是数组,因为你的宇宙在交易日可能相当标准化。

此外,我还必须假设代码是多线程的,并且curTickMap可能在setTickMap期间发生变化,因为很可能您没有在每个刻度上重置模型。

正如webclestic所指出的,你发布的代码不太可能编译。

哇,我的愚蠢是无止境的。。。

我解决了这个问题,它与tickmodel本身无关。提供的代码样本工作正常。显然,我太愚蠢了,无法确保使用正确的模型指针。

这就足够了:

void PriceModel::setTickMap( const QMap<QString,ITick*>& curTickMap ) {
    this->currentTicks = curTickMap;
    reset();
}
相关文章:
  • 没有找到相关文章