2016-06-16 7 views
1

バッファからデータを取り出してコンソールに出力するデータリーダーがあります。今私はリアルタイムでtexteditにデータを見たいと思います。 私は、データがテキストファイルからどのように(非リアルタイムで)読み込まれるかを示すいくつかの例を見てきました。データリーダ端末からリアルタイムでGUIにデータを取得

添付ファイルをご覧ください。ここで

/* Create a DataReader for the chatMessageTopic Topic (using the appropriate QoS). */ 
parentReader = chatSubscriber->create_datareader(
    chatMessageTopic.in(), 
    DATAREADER_QOS_USE_TOPIC_QOS, 
    NULL, 
    STATUS_MASK_NONE); 
checkHandle(parentReader.in(), "DDS::Subscriber::create_datareader"); 

/* Narrow the abstract parent into its typed representative. */ 
chatAdmin = Chat::ChatMessageDataReader::_narrow(parentReader.in()); 
checkHandle(chatAdmin.in(), "Chat::ChatMessageDataReader::_narrow"); 

/* Print a message that the MessageBoard has opened. */ 
cout << "MessageBoard has opened: send ChatMessages...." << endl << endl; 

while (!terminated) { 
    /* Note: using read does not remove the samples from 
     unregistered instances from the DataReader. This means 
     that the DataRase would use more and more resources. 
     That's why we use take here instead. */ 

    status = chatAdmin->take(
     msgSeq, 
     infoSeq, 
     LENGTH_UNLIMITED, 
     ANY_SAMPLE_STATE, 
     ANY_VIEW_STATE, 
     ALIVE_INSTANCE_STATE); 
    checkStatus(status, "Chat::ChatMessageDataReader::take"); 

    for (DDS::ULong i = 0; i < msgSeq->length(); i++) { 
     ChatMessage *msg = &(msgSeq[i]); 
     cout << msg->index << ": " << msg->content << endl; 
     fflush(stdout); 
    } 

    status = chatAdmin->return_loan(msgSeq, infoSeq); 
    checkStatus(status, "Chat::ChatMessageDataReader::return_loan"); 
+0

QtCreatorはIDEです。あなたはQtを使っています! –

+0

RTI Connext C++ APIを使用していると言えます。 –

+1

これはPrismtech C++プログラムです –

答えて

1

あなたはおそらく、あなたのUIは、1000Hzのでリフレッシュされることを望んでいません。したがって、ビジーなループでこのコードを実行することに意味はありません。代わりに、適度なリフレッシュレートで実行してください。 30Hz、タイマーから。

レッツ・抽象このうち:

class DDSProcessor : public QObject { 
    Q_OBJECT 
    QBasicTimer m_timer; 
    DDS::Subscriber * m_chatSubscriber; 
    Chat::ChatMessageDataReader * m_chatDataReader = nullptr; 
    ... 
    Q_SIGNAL void message(const QString &); 
    Q_SIGNAL void messages(const QStringList &); 
    void timerEvent(QTimerEvent * ev) { 
    if (ev->timerId() != m_timer.timerId()) return; 
    auto status = chatAdmin->take(
     msgSeq, 
     infoSeq, 
     LENGTH_UNLIMITED, 
     ANY_SAMPLE_STATE, 
     ANY_VIEW_STATE, 
     ALIVE_INSTANCE_STATE); 
    checkStatus(status, "Chat::ChatMessageDataReader::take"); 
    QStringList texts; 
    for (DDS::ULong i = 0; i < msgSeq->length(); i++) { 
     auto msg = &(msgSeq[i]); 
     auto text = tr("%1: %2").arg(msg->index).arg(msg->content); 
     texts << text; 
     emit message(text); 
    } 
    emit messages(texts); 
    status = chatAdmin->return_loan(msgSeq, infoSeq); 
    checkStatus(status, "Chat::ChatMessageDataReader::return_loan"); 
    } 
public: 
    void start() { 
    auto reader = m_chatSubscriber->create_datareader(
     m_chatMessageTopic.in(), ...); 
    checkHandle(read.in(), "DDS::Subscriber::create_datareader"); 
    m_chatDataReader = Chat::ChatMessageDataReader::_narrow(reader.in()); 
    checkHandler(m_chatDataReader.in(), "Chat::ChatMessageDataReader::_narrow"); 
    auto text = tr("MessageBoard had opened: send ChatMessages."); 
    emit message(text); 
    emit messages(text); 
    m_timer.start(this, 1000/30); 
    } 
    ... 
}; 

私は十分DDSライブラリに慣れていないよ、それはログの行のバッチだけでなく、個々の行を放出するのを助けることができるパフォーマンス上の理由から

、しかし、代わりに通知を受けるために使用しなければならないコールバックがいくつかあり、コールバックからシグナルを放出します。そうすれば、明示的なUI更新ループが不要になります。

あなたがUIにしなければならないすべては、その後、DDSProcessorによって送信されたメッセージに基づいて行動することです:

void setup(DDSProcessor * src, QTextEdit * dst) { 
    connect(src, &DDSProcessor::message, dst, &QTextEdit::append); 
} 

QTextEditQPlainTextEditの両方が非常に低速と高速のログ記録には適していないこと。最も簡単な回避策は、QListViewのリストモデルを使用し、バッチログエントリ信号を活用することです。

int main(int argc, char ** argv) { 
    QApplication app(argc, argv); 
    QStringListModel logModel; 
    QListView view; 
    DDSProcessor processor; 
    QObject::connect(&processor, &DDSProcessor::messages, &logModel, [&](const QStringList & texts){ 
    auto row = logModel.rowCount(); 
    logModel.insertRows(row, texts.count()); 
    for (auto const & text : texts) 
     logModel.setData(model.index(row++), text); 
    }); 
    view.setModel(&logModel); 
    view.show(); 
    view.setUniformItemSizes(true); // needed for performance 
    ... 
    return app.exec(); 
} 
0

は同期GUIにログインし、最小限の例です:

int main(int argc, char *argv[]) { 
    QApplication app(argc, argv); 
    QPlainTextEdit edit; 
    edit.show(); 
    int x = 0; 
    while (edit.isVisible()) { 
    x++; 
    edit.appendPlainText(QString("test %1").arg(x)); 
    qApp->processEvents(); 
    } 
    return 0; 
} 
+0

これは恐ろしいです。それはCPUを100%ペグする。それをしないでください。 –

+0

ループ内にいくつかのブロックIO操作を挿入しても、CPUを100%ロードすることはありません。データはどこかから来なければならない。この実装は、タイマーを使用せず、信号スロットシステムを動作させる必要がないため、実際にはシグナルベースの実装よりもCPUのコストが低い可能性があります。しかし、データが非常に小さなチャンクに入ってくる場合、何らかのバッファリングが役立つ可能性があります。 –

+0

GUIスレッド内のループ内の唯一の入出力IO操作は、 'app.exec()'内のevent-waitでなければなりません。それ以外の場合は応答性が損なわれます。このケースでは、データは、質問者が使用しているライブラリの別のワーカースレッドから来ています。そのライブラリはコールバックも提供していますので、私が提案したポーリングでさえ最善のことではありません - ビジースピニングはさらに悪い。 –

関連する問題