2016-07-09 17 views
0
aufgerufen wird

Ich versuche ein einfaches mehrseitiges Widget mit QStackedWidgets in Qt Creator mit Qt 4.8.6 zu erstellen. Das Ziel ist es, eine QLabel und QProgressBar verblassen zu lassen, nachdem der Fortschrittsbalken den vollen Wert erreicht. Ich dachte, der beste Weg, dies zu erreichen, war die Verwendung von QGraphicsOpacityEffect und QPropertyAnimation im Tandem wie unten zu sehen.QPropertyAnimation wird nicht sofort ausgeführt, wenn QAbstractAnimation :: start()

void MainWindow::AnimateStartScreen() 
{ 
    //QSound::play("./Audio/THX-DeepNote-48Khz.wav"); 
    sleep(5); 

    logoEffect = new QGraphicsOpacityEffect(); 
    logoAnimation = new QPropertyAnimation(logoEffect, "opacity"); 
    ui->startLogo->setGraphicsEffect(logoEffect); 
    logoAnimation->setDuration(2000); 
    logoAnimation->setStartValue(1); 
    logoAnimation->setEndValue(0); 
    logoAnimation->start(); 

    progressBarEffect = new QGraphicsOpacityEffect(); 
    progressBarAnimation = new QPropertyAnimation(progressBarEffect, "opacity"); 
    ui->startProgressBar->setGraphicsEffect(progressBarEffect); 
    progressBarAnimation->setDuration(2000); 
    progressBarAnimation->setStartValue(1); 
    progressBarAnimation->setEndValue(0); 
    progressBarAnimation->start(); 

    sleep(3); 
} 

die dann von der main Methode aufgerufen wird:

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    MainWindow w; 

    w.HideTitleBar(); 
    w.CenterWidget(); 
    //QMainWindow::showFullScreen(); 
    w.show(); 
    w.IncrementProgressbar(); 
    w.AnimateStartScreen(); 
    w.ChangePageTo(1); 

    return a.exec(); 
} 

Hier liegt das Problem. Ich möchte diese Animation zu beenden, bevor ich die Seite wie ändern, so:

void MainWindow::ChangePageTo(int page) 
{ 
    ui->stackedWidget->setCurrentIndex(page); 
} 

Gibt es eine Möglichkeit, ich Seitenwechsel verzögern kann, bis meine Animation abgeschlossen ist? Wenn ich den Seitenwechsel auskommentiere, scheint die Animation nicht einmal zu starten, bis QApplication::exec() in meiner main Methode aufgerufen wird, offensichtlich durch eine Wartezeit von 8 Sekunden (die Kombination aus beiden Schlafanrufen), anstatt eine 5 Sekunden Verzögerung vor QAbstractAnimation::start() wird genannt.

Ich glaube, was passiert, ist, dass die sleep(3) Zeile den Thread stoppt, in dem die GUI läuft, daher den Start der Animation für drei Sekunden verzögert. Wenn der Schlafanruf abgeschlossen ist, frage ich mich, ob die Animation versucht, fortzufahren, aber wegen des Seitenwechsels gibt es nur keinen sichtbaren Effekt vom schnellen Übergang.

Wie kann ich eine Verzögerung von 3 Sekunden machen, ohne den Thread zu stoppen, von dem die Animation abläuft? Oder gibt es andere Vorschläge, die den gleichen Effekt erzielen?

Antwort

1

Ich glaube, dass der Schlaf, was passiert ist (3), um den Faden zu stoppen, in dem der GUI auf

Fast sicher läuft. Damit die Animation ausgeführt werden kann, müssen Sie die Nachrichtenwarteschlange, die in dem von Ihnen geposteten Code ausgeführt wird, erst beim nächsten Aufruf von a.exec() ausführen.

Wenn Sie wirklich die Ausführung von MainWindow::AnimateStartScreen müssen blockieren, bis die Animation dann abgeschlossen ist vielleicht eine bessere Idee wäre, um den Anruf zu sleep(3) mit ...

while (progressBarAnimation->state() != QAbstractAnimation::Stopped) 
    QCoreApplication::processEvents(); 

zu ersetzen (Obwohl Sie vielleicht spielen mit den Flaggen zu QCoreApplication::processEvents passieren das genaue Verhalten Sie benötigen zu bekommen)

+0

Solche unendlichen Schleifen sind ein großer Aufwand und unnötige CPU-Auslastung. –

+0

Wie ist es eine Endlosschleife? 'QCoreApplication :: processEvents' verarbeitet die aktuell in die Warteschlange gestellten Ereignisse und kehrt dann zurück. Wenn eine Zeitüberschreitung erforderlich ist, rufen Sie die Überladung auf, die eine Zeitüberschreitung ermöglicht (daher mein Kommentar zum Festlegen der Flags usw.). –

+0

Ich meine, dass Sie nicht warten Ereignis, aber jeden Schritt einen Aufruf von 'processEvents'. Es ist ziemlich schwere Operation. Es gibt eine 'QEventLoop' Klasse für solche Dinge. Überprüfe meine Antwort. –

1

Verwenden nächste Muster für nicht-blockierend wartet (anstatt Schlaf).

QEventLoop loop; 
connect(progressBarAnimation, &QAbstractAnimaion::finished, &loop, &QEventLoop::quit); 
loop.exec();