3

さて、私は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);
}

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

4

2 に答える 2

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 を呼び出すと、冷蔵庫のマグネットがドアに追加されます :)

于 2009-04-03T23:54:51.093 に答える
7

You need to let the application's event loop run in order to keep the user interface updated. The easiest way to do this from your code is to call QApplication::processEvents() in your inner while loop.

Many people would consider your while loop to be inefficient - after all, you are just waiting for a given period of time to elapse. You may want to think about restructuring your code to use a timer instead.

You could create a QTimer object in your eye class's constructor, set a time-out of 5 seconds, and connect its timeout() signal to a slot in your eye class which updates the index into the set of slides and calls presentSlide(). You would start the timer in the playSequence() function.

于 2009-04-03T23:56:37.237 に答える