在QT中重新绘制小部件

时间:2017-05-01 08:41:06

标签: c++ qt

我有一段代码初始化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);

1 个答案:

答案 0 :(得分:0)

通常Qt使用其事件系统(由QWidget::update触发)定期更新屏幕以避免过多painting operations。因为您想要在for - 循环内更新屏幕而不返回主事件循环,所以默认方法不起作用。可能有不同的解决方案:

  1. 手动处理事件:您应该在整个等待时间内重复调用QCoreApplication::processEvents而不是QThread::usleep来处理所有新事件(来自{{ 1}})。请注意,您可能希望在删除和销毁QPropertyAnimation对象之前处理事件。

  2. 强制立即重新绘制屏幕您可以通过调用QWidget::repaint强制Qt立即重新绘制屏幕,​​这将调用{{ 1}}立即 此选项与Equalizer结合使用效果不佳。

  3. 使用计时器事件定期更新:删除paintEvent - 循环(和QPropertyAnimation函数调用)并定期使用QTimer对象执行一些行动。

  4. 请注意,选项3是与基于事件的系统一起使用的首选解决方案,例如Qt。