3

解像度が約15msのQtタイマーよりも正確なタイマーが必要なため、Windows APIのQueryPerformanceCounter()を使用して独自のタイマーを実装しようとしました。

私の最初のショットは、QObjectから継承し、毎秒信号を発する無限ループのタイマーを作成することでした。このタイマーをmoveToThread()を使用して独自のスレッドに移動しようとしました。これにより、メインウィンドウが毎秒更新され、すべてがブロックされることはありません。ただし、メインウィンドウが表示されることはなく、無限ループを削除すると->メインウィンドウが表示されます。

そこで、私はシングルショットアプローチを試しました。基本的な考え方は次のとおりです。

 connect( highPerformanceTimer, SIGNAL(timer_tick()), this, SLOT(timeOutSlot()) );
 connect( this,  SIGNAL(graphics_updated()), highPerformanceTimer, SLOT(timer_start()));

したがって、タイマーが作動すると、ui(opengl)が更新され、更新の最後に、タイマーを再起動するための信号が生成されます。

それでも、UI更新コードの最後からタイマーの再起動を削除しない限り、メインウィンドウは表示されません。

デバッガーでは、コードが正常に機能しているように見え、タイマーからUIにジャンプして戻ってきます。ブレークポイントがないと、突然のセグメンテーション違反が発生します。

問題が発生する可能性のあるヒントや、Qtでこれを実装するためのより良い方法があるかどうかを教えていただければ幸いです。

編集:もう少しコード

highperformancetimer.h

#ifndef HIGHPERFORMANCETIMER_H
#define HIGHPERFORMANCETIMER_H

#include <QObject>
#include <windows.h>

class HighPerformanceTimer : public QObject
{
    Q_OBJECT
public:
    HighPerformanceTimer();

signals:
    void timer_tick();

public slots:
    void timer_start();

private:
    // some variables
    LARGE_INTEGER highPerformanceCounterValue, highPerformanceCounterFrequency, highPerformanceCounterValueOld;
    int interval;
    float value;
    float last_tick_value;

};

#endif // HIGHPERFORMANCETIMER_H

highperformancetimer.cpp

#include "highperformancetimer.h"
#include "windows.h"
#include "QThread"


HighPerformanceTimer::HighPerformanceTimer()
{

    QueryPerformanceFrequency(&highPerformanceCounterFrequency);
}



void HighPerformanceTimer::timer_start(){
    float i = 0;
// just burn some time
    while( i<1000000 ) i++;
    emit HighPerformanceTimer::timer_tick();   
}

メインのOpenGlウィジェットからのいくつかのコード:

HighPerformanceTimer *highPerformanceTimer;
protected slots:
    virtual void timeOutSlot();

NeHeChapter5( QWidget *parent=0, char *name=0 ) : NeHeWidget( 50, parent, name )
    {
        highPerformanceTimer = new HighPerformanceTimer();

        connect( highPerformanceTimer, SIGNAL(timer_tick()), this, SLOT(timeOutSlot()) );
        connect( this,  SIGNAL(graphics_updated()), highPerformanceTimer, SLOT(timer_start()));
        highPerformanceTimer->moveToThread(&timerThread);
        highPerformanceTimer->timer_start();
    }

void NeHeChapter5::timeOutSlot(){
    timeOut();
}

void NeHeChapter5::timeOut()
{
    updateGL();
}

void NeHeChapter5::paintGL()
{
//opengl code *snip*
emit graphics_updated();
}
4

1 に答える 1

1

エラーはここにあります:

NeHeChapter5( QWidget *parent=0, char *name=0 ) : NeHeWidget( 50, parent, name )
{
    highPerformanceTimer = new HighPerformanceTimer();

    connect( highPerformanceTimer, SIGNAL(timer_tick()), this, SLOT(timeOutSlot()) );
    connect( this,  SIGNAL(graphics_updated()), highPerformanceTimer, SLOT(timer_start()));
    highPerformanceTimer->moveToThread(&timerThread);
    highPerformanceTimer->timer_start();
}

timer_start();を呼び出します。ではなく、呼び出し元のスレッドで呼び出されていtimerThreadます。また、あなたはあなたのスレッドを始めさえしませんでした。最初に電話してくださいtimerThread.start()。必要なスレッドでtimer_start()を呼び出すには、

QMetaObject::invokeMethod(highPerformanceTimer, "timer_start", Qt::QueuedConnection);

呼び出し元のスレッドではなく、新しく開始されたスレッドでtimer_startを呼び出します。

また、完全修飾名でtimer_tickを呼び出す必要はなく、次のemit HighPerformanceTimer::timer_tick();ように置き換えることができます。emit timer_tick();

于 2012-09-05T17:19:41.450 に答える