2009-04-03 5 views
3

だから私はQGraphicsSceneをeyeというクラスに持っています。各スライドを求めてQt:QGraphicsSceneは、私がそれを期待したとき更新していません

void eye::playSequence(int sequenceNum) { 

    for (int i=0; i<sequences[sequenceNum].numberOfSlides(); i++) { 
     presentSlide(sequenceNum, i); 
     time_t start; 
      time(&start); 
      bool cont=false; 
      while (!cont) { 
       time_t now; 
       time(&now); 
       double dif; 
       dif=difftime(now, start); 
       if (dif>5.0) 
        cont=true; 
      } 
    } 
} 

void eye::presentSlide(int sequenceNum, int slideNum) { 

    Slide * slide=sequences[sequenceNum].getSlide(slideNum); 

    QGraphicsPixmapItem * pic0=scene.addPixmap(slide->getStimulus(0)->getImage()); 
    pic0->setPos(0,0); 

    QGraphicsPixmapItem * pic1=scene.addPixmap(slide->getStimulus(1)->getImage()); 
    pic1->setPos(horizontalResolution-350,0); 

    QGraphicsPixmapItem * pic2=scene.addPixmap(slide->getStimulus(2)->getImage()); 
    pic2->setPos(horizontalResolution-350,verticalResolution-450); 

    QGraphicsPixmapItem * pic3=scene.addPixmap(slide->getStimulus(3)->getImage()); 
    pic3->setPos(0,verticalResolution-450); 
} 

を今は、私は、次のを表示し、5秒間待って、これは画像の1セットを表示することを期待し、そうでしょう、私は関数を呼び出しますに。代わりに、すべてのスライドが処理され最後の4つの画像が表示されるまで何も表示されません。私はイメージすることができたすべての場所でscene.update()と呼ぶことを試みたが、何もしなかった。 playSequence関数が返ってきたときだけシーンが更新されるようです。ここで何が起こっているのでしょうか?

答えて

7

これは、イベント駆動型のGUIフレームワークで連続アニメーションを行いたい場合によく見られるような動作です。私は、eye :: playSequenceがボタンのクリックから呼び出されるか、アプリケーション起動コード中のある時点から呼び出されると思いますか?いずれにせよ、ここでは何が起こっているのですか?

Qtはメインアプリケーションスレッドを使用してイベントループを駆動します。イベントループは次のようなものです:

while(app_running) 
{ 
    if(EventPending) 
    ProcessNextEvent(); 
} 

表示されている問題は、ペイントイベント中に画面の更新が行われていることです。マウスクリックイベントまたはその他のイベント中にコードを実行している場合、実行中のすべての描画がキューイングされ、次のペイントイベントで画面に描画されます。場合によっては、これが沈むのにしばらく時間がかかります。

これを解決する最善の方法は、アプローチを少し変更することです。 1つの方法は、あなたのwhileループを捨て、QTimerが5秒ごとに起動するように設定することです。タイマースロットでは、1つのスライドを描くことができます。タイマーが再び発生すると、次のスライドなどを描画します。

即時性の低いクイックフィックスが必要な場合は、presentSlide(sequenceNum、i)の呼び出しの直後にqapp-> processEvents()を呼び出してみてください。これにより(ほとんどの場合)アプリケーションは、ペイントイベントを含むべきキューに入れられたすべてのイベントをクリアするよう強制されます。

また、eye :: presentSlide()は、最後の呼び出しで追加されたものをカバーする各繰り返しでシーンに新しいシーンオブジェクトを追加するだけであることにも言及する必要があります。シーンを冷蔵庫のドアと呼び、scene()を呼び出すとaddXXXはドアに冷蔵庫のマグネットを多く投げています:)

7

ユーザーインターフェイスを更新するために、アプリケーションのイベントループを実行させる必要があります。あなたのコードからこれを行う最も簡単な方法は、あなたの内側whileループでQApplication :: processEvents()を呼び出すことです。

あなたのwhileループは非効率的であると考えられます。結局のところ、一定の時間が経過するのを待っているだけです。代わりにタイマーを使用するようにコードを再構成することを考えてみてください。

アイクラスのコンストラクタでQTimerオブジェクトを作成し、タイムアウトを5秒に設定し、eyeクラスのスロットにtimeout()シグナルを接続してインデックスをスライドとコールのセットに更新できますpresentSlide() playSequence()関数でタイマーを開始します。

関連する問題