0

カスタム 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<...> ) メソッドを呼び出すと、モデルがテーブルビューに入力され、すべての異なる株式が期待どおりに表示されます。(私のモデルのデータの初期化は正常に機能しています)

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 を介して編集することは想定されておらず、テーブルウィジェットを使用してデータを表示することもできましたが、このモデル情報を共有する別のビューがあるかどうかはわかりません。現在の価格のマップはそれほど大きくない (25 アイテムがトップ) ため、新しい価格が入るたびにモデルをリセットするのは不快ではありません.

事前に感謝します。誰かがこのマイクロポートで私を助けてくれることを願っています

4

2 に答える 2

0

リアルタイムのティックデータを表示していることを考えると、データストレージにアプローチすることをお勧めします。ティックから5つのアイテムしか表示していないので、他のことを検討したい場合があります。取引日中にユニバースがかなり標準化されている可能性があるため、QMapは配列である可能性があります。

また、コードはマルチスレッドであり、ティックごとにモデルのリセットを行っていない可能性があるためcurTickMap、の間に変更される可能性があると想定する必要があります。setTickMap

そして、webclecticが指摘したように、あなたが投稿したコードはコンパイルされそうにありません。

于 2012-01-16T04:57:15.763 に答える
0

うわー、私の愚かさは際限がありません...

私は問題を修正しましたが、それは tickmodel 自体とは何の関係もありませんでした。提供されたコードサンプルは問題なく動作します。私は明らかに、正しいモデルポインタが使用されていることを確認するにはあまりにも愚かでした。

これで十分です:

void PriceModel::setTickMap( const QMap<QString,ITick*>& curTickMap ) {
    this->currentTicks = curTickMap;
    reset();
}
于 2012-01-16T13:18:14.623 に答える