我有一段代码初始化QWidget的实例,将其放在布局中并调用动画。所有这一切都发生在循环中。我遇到了每次迭代同时绘制动画的问题,完全忽略了QThread :: usleep()。有没有办法以正确的方式清理布局,以便我能达到预期的效果?
double randomTestArray[numOfPoints];
double fMin = 0;
double fMax = 20;
srand(time(NULL));
for(int p = 0 ; p < 100 ; p++)
{
Equalizer * eq = new Equalizer();
ui->verticalLayout->addWidget(eq);
for(int i = 0 ; i < numOfPoints ; i++)
{
randomTestArray[i] = fMin + (double)rand() * (fMax - fMin) / RAND_MAX;
}
eq->setChunk(&randomTestArray[0] , &startArray[0]);
ui->verticalLayout->removeWidget(eq);
delete eq;
QThread::usleep(1000);
}
使用setChunk()方法中的QPropertyAnimation和paintEvent()完成动画。如果您需要更多代码,请通知我。
添加均衡器类的细分:
void Equalizer::setChunk(double *chunk, int * startYArr)
{
if(*startYArr == -1)
{
for(int i = 0 ; i < 24 ; i++)
{
*(startYArr + i) = 150;
}
}
int xCoordinateArray[24];
int yCoordinateArray[24];
for(int i = 0 ; i < 24 ; i++)
{
yCoordinateArray[i] = *(chunk + i) * 5;
xCoordinateArray[i] = 100 + i*25;
}
cout << "Chunk initialized" << endl;
cout << "Start Coordinates : " << endl;
for(int i = 0 ; i < 24 ; i++)
{
cout << startYArr[i] << endl;
}
cout << "End Coordinates : " << endl;
for(int i = 0 ; i < 24 ; i++)
{
cout << yCoordinateArray[i] << endl;
}
QPropertyAnimation *animation = new QPropertyAnimation(this , "nrect");
animation->setDuration(2000);
animation->setStartValue(QRect(xCoordinateArray[0] , *(startYArr + 0) , 10 , 10));
animation->setEndValue(QRect(xCoordinateArray[0] , 150 - yCoordinateArray[0] , 10 , 10));
animation->start();
connect(animation, &QPropertyAnimation::valueChanged , [=](){update();});
QPropertyAnimation *animation2 = new QPropertyAnimation(this , "nrect2");
animation2->setDuration(2000);
animation2->setStartValue(QRect(xCoordinateArray[1] , *(startYArr + 1), 10 , 10));
animation2->setEndValue(QRect(xCoordinateArray[1] , 150 - yCoordinateArray[1] , 10 , 10));
animation2->start();
connect(animation2, &QPropertyAnimation::valueChanged , [=](){update();});
QPropertyAnimation *animation3 = new QPropertyAnimation(this , "nrect3");
animation3->setDuration(2000);
animation3->setStartValue(QRect(xCoordinateArray[2] , *(startYArr +2) , 10 , 10));
animation3->setEndValue(QRect(xCoordinateArray[2] , 150 - yCoordinateArray[2] , 10 , 10));
animation3->start();
connect(animation3, &QPropertyAnimation::valueChanged , [=](){update();});
................................
for(int i = 0; i < 24 ; i++)
{
*(startYArr + i) = yCoordinateArray[i];
}
void Equalizer::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QRect ellipse(mRect);
QPainter painter(this);
painter.setBrush(Qt::red);
painter.drawEllipse(ellipse);
QRect ellipse2(mRect2);
painter.setBrush(Qt::red);
painter.drawEllipse(ellipse2);
QRect ellipse3(mRect3);
painter.setBrush(Qt::red);
painter.drawEllipse(ellipse3);
.............................
尝试解决方案:
eq->setChunk(&randomTestArray[0] , &startArray[0]);
QCoreApplication::processEvents();
ui->verticalLayout->removeWidget(eq);
QThread::usleep(1000);
答案 0 :(得分:0)
通常Qt使用其事件系统(由QWidget::update
触发)定期更新屏幕以避免过多painting operations。因为您想要在for
- 循环内更新屏幕而不返回主事件循环,所以默认方法不起作用。可能有不同的解决方案:
手动处理事件:您应该在整个等待时间内重复调用QCoreApplication::processEvents
而不是QThread::usleep
来处理所有新事件(来自{{ 1}})。请注意,您可能希望在删除和销毁QPropertyAnimation
对象之前处理事件。
强制立即重新绘制屏幕:您可以通过调用QWidget::repaint
强制Qt立即重新绘制屏幕,这将调用{{ 1}}立即
此选项与Equalizer
结合使用效果不佳。
使用计时器事件定期更新:删除paintEvent
- 循环(和QPropertyAnimation
函数调用)并定期使用QTimer
对象执行一些行动。
请注意,选项3是与基于事件的系统一起使用的首选解决方案,例如Qt。