Qt, zatrzymywanie się animacji GIF w trakcie przesuwania etykietki

0

Hej! Napisałem jakiś programik, chciałem dodać animację GIF z przezroczystością.
Udało mi się to stosując etykietke (QLabel) i klasę QMovie...
Problem w tym, że jak przesuwam etykietkę w pętli (co 1 ms jest pauza), to animacja się zatrzymuje... Po przesunięciu do miejsca docelowego to z powrotem się odtwarza... Kod

    ui->setupUi(this);
    Wysokosc = 0;
    QMovie *movie1 = new QMovie(ui->label);
    movie1->setFileName(":/zasoby/animdome_e0.gif");
    movie1->setCacheMode(QMovie::CacheAll);
    ui->label->setMovie(movie1);
    movie1->start();
......

// tutaj klasa, dzięki której mogę wstrzymywać działanie aplikacji

class SleepThread : public QThread{
     Q_OBJECT
     // private run
     void run (){}

     public :
     static void usleep(long iSleepTime){
          QThread::usleep(iSleepTime);
     }
     static void sleep(long iSleepTime){
          QThread::sleep(iSleepTime);
     }
     static void msleep(long iSleepTime){
          QThread::msleep(iSleepTime);
     }
};
// ...
// tutaj jest przesuwany obrazek (animowany gif) w dół, po wciśnięciu przycisku

void MainWindow::on_pushButton_2_clicked()
{
    QApplication::sendPostedEvents();
    for (int i = 0; i<100; i++)
    {
        update();
        repaint();
       // ui->label->setUpdatesEnabled(TRUE);
        ui->label->setGeometry(100, Wysokosc++, 160, 120);


        SleepThread::msleep(1);

        ui->label->update();
        ui->label->repaint();



    }

 

Wszystko jest ok, tylko jak przesuwam label z animowanym gifem to animacja na czas przesunięcia się zatrzymuje....
Zrobiłem coś podobnego w C# i Windows Forms (.NET 4.0) i tam przesuwanie pictureBoxa z animowanym gifem nie powoduje zatrzymania animacji w tym pictureBoxie....
Może w Qt animacja jest w tym samym głównym wątku co aplikacja?

1

Znalazłem rozwiązanie, w pętli należy wywołać funkcję :

        QApplication::processEvents(QEventLoop::AllEvents, 100);
 

natomiast przed pętlą :

QApplication::sendPostedEvents(); 

np. :

    QApplication::sendPostedEvents();
    for (int i = 0; i<100; i++)
    {
        QApplication::processEvents(QEventLoop::AllEvents, 100);
        update();
        repaint();
        ui->label->setGeometry(100, Wysokosc++, 160, 120);
        ui->label->update();

Za dokumentacją :

void QCoreApplication::processEvents ( QEventLoop::ProcessEventsFlags flags, int maxtime )
This function overloads processEvents().

Processes pending events for the calling thread for maxtime milliseconds or until there are no more events to process, whichever is shorter.

You can call this function occasionally when you program is busy doing a long operation (e.g. copying a file). 
void QCoreApplication::sendPostedEvents ( QObject * receiver, int event_type ) [static]
Immediately dispatches all events which have been previously queued with QCoreApplication::postEvent() and which are for the object receiver and have the event type event_type.

Generalnie przypomniało mi to trochę sytuację z Delphi i C+ Buildera (biblioteka VCL), tam też był podobny myk przy przesuwaniu obrazków na formularzu (tam to było odpowiedni Application.ProcessMessages; lub Application->ProcessMessages(); )

0

Powiedzenie, że masz to totalnie źle to jest łagodne stwierdzenie.

QPropertyAnimation *animation = new QPropertyAnimation(ui->label, "pos");
 animation->setDuration(10000);
 animation->setStartValue(QPoint(100, 0));
 animation->setEndValue(QPoint(100, 100));

 animation->start(QAbstractAnimation::DeleteWhenStopped);
0

A czemu źle? Pytam się bo nie znam Qt dobrze, a ten kod gdzieś znalazłem w internecie....

1

powodów jest kilka:
#zamrażasz wątek główny sleepem (akurat czas jest krótki, więc nie odczuwasz bólu)
#wymuszasz repaint całości (możesz ze swojego kodu to wywalić repaint oraz update i nadal będzie działać), zamiast pozwolić Qt zrobić to w sposób optymalny
#zupełnie nie rozumiesz co się dzieje, po prostu upchałeś w losowe miejsca sendPostedEvents oraz processEvents i akurat złożyło się do postaci, która działa. Najlepszym dowodem twojego "kodowania przez permutację" jest klasa SleepThread, która jest ci zupełnie niepotrzebna.
#Qt dostarcza gotowe rozwiązania do animacji (dałem kod)

0

Dzięki! :)
Po prostu nie wiedziałem tego. Heh, człowiek uczy się całe życie... :D :-)

1 użytkowników online, w tym zalogowanych: 0, gości: 1