2017-05-01 2 views
2

QWidget의 인스턴스를 초기화하고 레이아웃 안에 배치하고 애니메이션을 호출하는 코드 조각이 있습니다. 그 모든 일이 반복되고 있습니다. QThread :: usleep()을 완전히 무시하면서 애니메이션을 그리는 각 반복의 문제가 발생했습니다. 원하는 결과를 얻을 수 있도록 올바른 방법으로 레이아웃을 정리할 수있는 방법이 있습니까?QT에서 위젯 다시 그리기

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

"for (int p = 0; p <1; p ++)"- 정말요? 또한,'Equalizer' 인스턴스를 만들고, 레이아웃에 추가하고,'setChunk'를 호출하고, 레이아웃에서 제거하고,'Qt' 이벤트 루프로 돌아 가지 않고 모두 삭제하는 것처럼 보입니다. 나는 당신이 [MCVE]를 제공해야한다고 생각합니다. –

+0

"Qt 이벤트 루프로 돌아 가기"란 무엇을 의미합니까? –

+0

'Qt'는 이벤트 기반입니다. QObject 파생 클래스의 인스턴스에 대해 함수를 호출하면 일반적으로 하나 이상의 이벤트가 해당 객체에 게시됩니다. 이러한 이벤트를 처리하려면 이벤트 루프를 실행해야합니다. –

답변

0

일반적으로 Qt는 주기적으로 painting operations 너무 많이 피하기 위해 화면을 업데이트 (QWidget::update에 의해 트리거)의 이벤트 시스템을 사용합니다. 메인 이벤트 루프로 돌아 가지 않고 for -loop 내의 화면을 업데이트하려고하므로 기본 접근 방식이 작동하지 않습니다. 다른 솔루션이 가능합니다 :

  1. 수동으로 이벤트를 처리 : 당신은 (QPropertyAnimation에서 오는) 모든 새로운 이벤트를 처리하는 대신 QThread::usleep의 전체 대기 시간 동안 반복적으로 QCoreApplication::processEvents를 호출해야합니다. Equalizer 객체를 제거하고 파기하기 전에 이벤트를 처리하고 싶을 것입니다.

  2. 힘은 바로 화면을 다시 칠하기 : 당신은 즉시 paintEvent를 호출하는 QWidget::repaint를 호출하여 즉시 화면을 다시 칠하는 Qt를 강제 할 수 있습니다.
    이 옵션은 QPropertyAnimation과 함께 사용할 수 없습니다. for -loop (및 usleep 함수 호출)를 제거하고 주기적으로 어떤 작업을 수행 할 QTimer 객체를 사용

  3. 사용 타이머 이벤트는 주기적으로 업데이트합니다.

옵션 3은 Qt와 같은 이벤트 기반 시스템에서 사용하기에 더 적합한 솔루션입니다.

+0

나는이 모든 접근법을 시도했지만 루프 이후에만 그림을 그리기 시작합니다. 질문의 마지막에 추가했습니다. –

+0

옵션 3에는 더 이상 for 루프가 없습니다. 따라서 이벤트 루프 이후에 애니메이션이 시작되는 것은 불가능합니다. – m7913d

+0

QPropertyAnimation을 사용하고 있다는 사실을 간과 했으므로 첫 번째 접근 방식을 업데이트했습니다. 옵션 3은 필자가 선호하는 솔루션입니다. – m7913d