2012-01-15 47 views
0

我對自定義qabstracttablemodel的更新有很大的麻煩。 我想要一個表格顯示幾個股票的價格。我從我控制的本地服務器獲取價格。此設置僅用於測試目的。定價信息在工作者線程中接收。C++ qt qabstracttablemodel子類在更新底層qmap時崩潰

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

模型填充的tableview當我打電話setTickMap(

我已經通過以下方式子類的qabstracttablemodel qmap < ...>)方法,並顯示所有不同的股票,正如預期。 (初始化我的模型中的數據工作正常)

問題出現時,我想再次調用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項TOPS),所以我不舒服模型重置每個新的價格在未來。提前

感謝,我希望有人能幫助我這個 micropor

+0

你確定這編譯? 'currentTicks'是一個'QMap ',而你的'setTickMap'作爲'QMap '的參數。 – pnezis 2012-01-15 23:28:14

+0

我很抱歉,但爲了讓問題更容易,我將自定義接口IInstrument更改爲像qstring這樣已知的東西... – MicroPor 2012-01-16 07:12:39

回答

0

哇我的愚蠢無國界...

我解決了這一問題,它沒有任何關係與tickmodel本身。提供的codesamples工作得很好。我顯然是太愚蠢了,以確保使用正確的模型指針。

這足以:

void PriceModel::setTickMap(const QMap<QString,ITick*>& curTickMap) { 
    this->currentTicks = curTickMap; 
    reset(); 
} 
0

考慮到您正在顯示實時tickdata,我建議您接近數據存儲。既然你只顯示了勾號中的5項,你可能想考慮其他的東西,那麼QMap可能是數組,因爲你的宇宙在交易日可能相當標準化。

此外,我將不得不假設代碼是多線程的,並且curTickMap可能會在setTickMap期間發生更改,因爲您很可能沒有對每個打勾執行模型重置。

而且webclectic指出你發佈的代碼不太可能編譯。