[solved] Why my gif looks like an image ...?



  • My gif doesn't work on MyMessageBox *m but it's work on MyMessageBox msg.
    I don't know why. On MyMessageBox *m i see just one image of gif but it's block like an image.

    @
    MyMessageBox msg(this);
    msg.setText(tr("Une reconstruction de la base de donnée est demandé.\nVoulez vous l'effectuer maintenant?"));
    QPixmap p(":/icones/error");
    p=p.scaled(150,150);
    msg.setIconPixmap(p);
    msg.setTextYesButton(tr(" OUI "));
    msg.setTextNoButton(tr(" NON "));
    msg.setFont(QFont("Utsaah",17));
    msg.setSize(700,300);

        if (msg.exec() == MyMessageBox::Accepted)
        {
            MyMessageBox *m = new MyMessageBox(this);
            m->setText(tr("Attendre la fin de la reconstruction de la base de donnée."));
            QMovie *mov = new QMovie(":/gif/wait"); // ????
            m->setStartMovie(mov);
            m->show();
            qApp->processEvents();
            QSqlQuery q;
            q.exec("VACUUM");
            mFile.close();
            if(mFile.open(QIODevice::WriteOnly))
                time <<  QDateTime::currentDateTime().toString("yyyy-MM-dd HH.mm.ss.zzz");
            m->hide();
        }
    

    @

    Here the constructor of MyMessageBox
    @
    MyMessageBox::MyMessageBox(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::MyMessageBox)
    {
    ui->setupUi(this);
    this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
    this->setAttribute(Qt::WA_AcceptTouchEvents);
    this->setWindowModality(Qt::WindowModal);
    }
    @

    Méthode setStartMovie
    @
    void MyMessageBox::setStartMovie(QMovie *m)
    {
    ui->label_image->setMovie(m);
    m->start();
    }
    @


  • Moderators

    There are several serious problems with this code.
    @
    MyMessageBox msg(this);
    @
    I hope this is a local variable. Otherwise it will most probably crash your app when "this" is destroyed and tries to delete its child.
    @
    MyMessageBox *m = new MyMessageBox(this);
    @
    You are never deleting this so it will live as long as "this" is alive. If you call this entire function more then once you will create several copies of that message box.
    @
    QMovie *mov = new QMovie(":/gif/wait");
    @
    Now you are leaking memory. You never delete this movie object and docs clearly state that the label does NOT take ownership of it.
    @
    qApp->processEvents();
    @
    This will process events ONCE. From there, up to the closing brace, your UI is frozen. This is why you're not seeing any animation. It has nothing to do with whether the MyMessageBox is created on the stack or the heap.



  • I just want to show a message box during this action :
    @
    QSqlQuery q;
    q.exec("VACUUM");
    @

    To show a messagebox I put :
    @
    MyMessageBox m(this);
    m.setText(tr("Attendre la fin de la reconstruction de la base de donnée."));
    m.show();

    QSqlQuery q;
    q.exec("VACUUM");

    m.hide();
    @

    But the message box appears only if the "VACUUM" takes a lot of time (more than 5 sec)
    It's for that I have added after the show(): @qApp->processEvents();@

    The message works perfectly like this.
    Now I want insert gif but like this:
    @
    MyMessageBox m(this);
    m.setText(tr("Attendre la fin de la reconstruction de la base de donnée."));
    QMovie *mov = new QMovie(":/gif/wait"); // ????
    m.setStartMovie(mov);
    m.show();
    mov->start();

    QSqlQuery q;
    q.exec("VACUUM");

    m.hide();
    delete mov;
    @

    But it dosen't work... with or without @qApp->processEvents();@


  • Moderators

    I can only repeat myself.

    No, the message box does not work perfectly like this. It's just displayed once but it's non-responsive because there's no event loop running between show() and hide(). Have you tried to click a button in it? It won't respond because it's frozen. If your query takes long OS will show your app as non-responsive. There's no event loop so there's no animation either.

    The proper solution is to run your query in a worker thread and show the dialog via exec() instead of show/hide. exec() runs a proper event loop. The dialog will be responsive and your animation will play.
    Before you try it - don't mix exec and the query in the same thread. exec() is blocking so it won't work.

    Btw. you should not delete mov while you're still using it. Check your scopes.



  • Thanks for your help but how can i do this correctly ?

    @
    MyMessageBox *m = new MyMessageBox(this);
    m->setText(tr("Attendre la fin de la reconstruction de la base de donnée."));
    QMovie *mov = new QMovie(":/gif/wait"); // ????
    m->setStartMovie(mov);
    mov->setParent(m);
    mov->start();
    connect(this, SIGNAL(endVacuum()), m, SLOT(deleteLater()));
    QtConcurrent::run(this, &MainWidget::vacuum);
    m->exec();
    @

    @
    void MainWidget::vacuum()
    {
    QString path ="C:/lastvacuum";
    QFile mFile(path);
    QTextStream time(&mFile);
    QSqlQuery q;
    q.exec("VACUUM");

    if(mFile.open(QIODevice::WriteOnly))
        time <<  QDateTime::currentDateTime().toString("yyyy-MM-dd HH.mm.ss.zzz");
    mFile.close();
    emit endVacuum();
    

    }
    @

    If I do that my gif works but I find it's so complicated just for showing a message to say at the customer that works...


  • Moderators

    It's not that complicated. A single function that runs asynchronous operation is pretty simple if you ask me.
    It wouldn't look so messy if you encapsulated things properly, eg. put stuff where it belongs:
    @
    //all the other setup should be inside the message box constructor
    //don't construct an object outside of it
    MyMessagebox m(this, tr("Attendre la fin de la reconstruction de la base de donnée."), ":/gif/wait");
    ...
    m.exec();
    @
    and split the vacuum method into something like executeQuery(QString query) and storeTime(QSting fileName).
    Just because something is in one function doesn't make it "easier". It's actually harder, because the next guy who reads it will have to dig through all that boilerplate that could be hidden behind well-named methods. It also makes things harder to reuse and encourages copy/paste programming.
    For example if you create a storeTime method it's quite possible that you can use it somewhere else.
    If you happen to need only to store time and not execute a query you might look at the vacuum() and think "oh, this does what I need but also this other stuff so I can't use it. I'll just copy over the part I need..." and that's bad for maintainability.
    Split your stuff. One function (or class) should do ONE thing. Stuffing everything into one function leads to "Spaghetti code":http://en.wikipedia.org/wiki/Spaghetti_code and "God Objects":http://en.wikipedia.org/wiki/God_object



  • Normaly MyMessageBox it's simple dialog with button YES/NO.
    But here I want use this Class to do a "popup" message (without any button).
    it's for that I define my text and other attributes.
    It's not the class MyMessageBox which I find complicated, but the method to call vacuum.
    @
    QtConcurrent::run(this, &MainWidget::vacuum);
    @


  • Moderators

    I don't, so I guess you'll have to get a third opinion to have a democratic result ;)



  • [quote author="Chris Kawa" date="1416575416"]I don't, so I guess you'll have to get a third opinion to have a democratic result ;)[/quote]

    Anyway it's work with your help. Thanks


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.