[英]c++ qt qabstracttablemodel subclass chrashes when underlying qmap is updated
我在更新自定义qabstracttablemodel时遇到了很大的麻烦。 我想用一张表格显示几只股票的价格。 我从我控制的本地服务器上获得价格。 此设置用于测试目的。 定价信息在工作线程中接收。
我已经通过以下方式将qabstracttablemodel子类化:
PriceModel.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;
};
PriceModel.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 <...>)方法时,该模型填充tableview,并且所有不同的股票都按预期显示。 (在我的模型中初始化数据工作正常)
当我想再次调用setTickMap(qmap <...>)方法时,就会出现问题。 该应用程序崩溃了,我不明白为什么我也没有得到明显的错误消息-即segvault。
在调试配置崩溃时,netbeans将打开一个名为“ Disassemlby”的选项卡,其中包含以下内容:
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个项目),因此我对每次出现的新价格重置模型并不感到不适。
在此先感谢,我希望有人可以帮助我
考虑到您正在显示实时报价数据,我建议您使用数据存储。 由于您仅显示报价中的5个项目,因此您可能需要考虑其他事项,因此QMap可能是数组,因为您的Universe在交易日内可能已经相当标准化。
我还必须假定代码是多线程和curTickMap
可以在过程中更改setTickMap
,因为它很可能是你没有做对每一个刻度模型复位。
正如webclectic指出的那样,您发布的代码不太可能进行编译。
哇,我的愚蠢无止境...
我解决了这个问题,它与tickmodel本身无关。 提供的代码样本工作正常。 我显然太愚蠢以至于无法确保使用正确的Modelpointer。
这足够了:
void PriceModel::setTickMap( const QMap<QString,ITick*>& curTickMap ) {
this->currentTicks = curTickMap;
reset();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.