Qtは:私はそれを期待するときQGraphicsSceneが更新されません
-
23-08-2019 - |
質問
[OK]をので、私は、クラスと呼ばれる目で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
関数が返した場合にのみ、更新のシーンのように思えます。すべてのアイデアは、ここで何が起こっているかもしれない?
解決
これは、1つの連続したアニメーションをしたいとき、多くの場合、イベントドリブンGUIフレームワークに見られる行動の一種です。私はその目::再生手順ボタンクリックまたは多分アプリケーションのスタートアップコード中のある時点から呼び出されると推測するつもりですか?いずれにせよ、ここで何が起こっているかです。
Qtはイベントループを駆動するためのメインのアプリケーションスレッドを使用します。イベントループはこのようなものです。
while(app_running)
{
if(EventPending)
ProcessNextEvent();
}
あなたが見ている問題は、画面の更新がペイントイベント中に行われていることです。あなたは、マウスのクリックイベントや他のイベント中にいくつかのコードを実行している場合は、あなたがやっているすべての描画がキューに登録され、次のペイントイベントで画面に描画されます。時にはそれが中に沈み、このためにしばらくかかります。
この問題に対処する最良の方法は、あなたのアプローチビットを変更することです。 1つの方法は、whileループとセットアップ5秒ごとに起動するように設定QTimerを捨てることです。タイマースロットでは、1枚のスライドを描くことができます。タイマー火災は再び、次のスライドなどを描くときます。
あなたはより直接的かつ少ない上品なクイックフィックスをしたい場合は、、(qapp->のprocessEventsを呼び出してみてください)右presentSlide(sequenceNum、I)へお電話した後。これは(ほとんどの時間)は、任意のペイントイベントを含める必要があり、イベントをキューに入れてクリアするアプリケーションを強制されます。
私も、その目を言及する必要があります:: presentSlide()単に最後の呼び出しの間に追加されたものをカバーし、各反復でシーンに新しいシーンオブジェクトを追加しています。冷蔵庫のドアなどのシーンを考えると、あなたがシーンを()を呼び出すときaddXXXあなたはドアの上に多くの冷蔵庫用マグネットを投げている:。)
他のヒント
あなたは、アプリケーションのイベントループが更新されたユーザインタフェースを維持するために実行できるようにする必要があります。あなたのコードからこれを行う最も簡単な方法は、あなたの内側のwhileループではQApplication ::のprocessEvents()を呼び出すことです。
多くの人があなたのwhileループは非効率的であると考えるでしょう - 結局、あなただけが経過する所定の時間を待っています。あなたが代わりにタイマーを使用するようにコードを再構築について考えたいことがあります。
あなたは、あなたの目のクラスのコンストラクタでQTimerオブジェクトを作成し、5秒のタイムアウトを設定し、スライドのセットにインデックスを更新しpresentSlideを呼び出して、あなたの目のクラスのスロットにそのタイムアウト()信号を接続することができ()。あなたは、再生手順()関数で、タイマーを開始します。