好的,所以我在一个名为eye的课程中有一个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秒,然后显示下一个,依此类推。相反,它只显示所有幻灯片,然后显示最后四个图像。我试过在我能想象的每个地方都打电话给scene.update()
而且它没有做任何事情。似乎场景仅在playSequence
函数返回时更新。任何想法可能会在这里发生什么?
答案 0 :(得分:7)
当想要进行连续动画时,这种事件通常出现在事件驱动的GUI框架中。我想猜测eye :: playSequence是从点击按钮调用还是从应用程序启动代码中的某个点调用的?无论如何,这是正在发生的事情。
Qt使用主应用程序线程来驱动事件循环。事件循环是这样的:
while(app_running)
{
if(EventPending)
ProcessNextEvent();
}
您看到的问题是屏幕更新是在绘画事件期间完成的。如果您在鼠标单击事件或任何其他事件期间运行某些代码,则您正在执行的所有绘图都将排队,并将在下一个绘制事件中绘制到屏幕上。有时需要一段时间才能沉入其中。
解决这个问题的最佳方法是稍微改变一下你的方法。一种方法是扔掉你的while循环并设置QTimer设置每5秒触发一次。在计时器插槽中,您可以绘制一张幻灯片。当计时器再次触发时,绘制下一张幻灯片等
如果您想要更直接,更不优雅的快速修复,请在调用presentSlide(sequenceNum,i)后立即尝试调用qapp-&gt; processEvents()。这(大部分时间)将强制应用程序清除任何应包括绘制事件的排队事件。
我还应该提一下,eye :: presentSlide()只是在每次迭代时向场景中添加新的场景对象,覆盖在上次调用期间添加的场景对象。把这个场景想象成一个冰箱门,当你打电话给场景()时,addXXX你在门上扔了更多的冰箱磁铁:)
答案 1 :(得分:7)
您需要让应用程序的事件循环运行,以便更新用户界面。从代码中执行此操作的最简单方法是在内部while循环中调用QApplication :: processEvents()。
很多人会认为你的while循环效率低下 - 毕竟,你只是等待一段时间才能过去。您可能需要考虑重构代码以使用计时器。
您可以在眼睛类的构造函数中创建一个QTimer对象,设置超时5秒,并将其timeout()信号连接到眼睛类中的一个插槽,该插槽将索引更新为幻灯片组并调用presentSlide ()。你可以在playSequence()函数中启动计时器。