Как правильно уничтожить объект QMovie и QLabel при переходи из заставки в основную программу

Решил добавить красивую заставку при загрузки программы. Сделал гифку. Добавил ее в main. Но при старте программы гифка не уничтожается и продолжает грузить процессор.

Как нужно правильно, переходить из заставки в основную программу?

MainWindow w;

SoftKeyBoardContext * ic = new SoftKeyBoardContext();

a.setInputContext(ic);

w.setWindowFlags(Qt::FramelessWindowHint);

QMovie *movie = new QMovie("./image/Titul.gif");

QLabel *processLabel = new QLabel();

processLabel->resize(640,480);

processLabel->setMovie(movie);

processLabel->setWindowFlags(Qt::FramelessWindowHint);

processLabel->setAlignment(Qt::AlignCenter);

processLabel->setGeometry(  QStyle::alignedRect(Qt::LeftToRight,Qt::AlignCenter,processLabel->size(),qApp->desktop()->availableGeometry())         );

movie->start();

processLabel->show();

QTimer::singleShot(5000, processLabel, SLOT(close()));

QTimer::singleShot(4500, &w, SLOT(show()));

Сделал по новому:

  #include "mainwindow.h"
  #include <QApplication>
  #include <QTextCodec>
  #include "SoftKeyBoardContext.h"

  #include <unistd.h>
  #include <sys/ioctl.h>
  #include <fcntl.h>
  #include <linux/ioctl.h>
  #include <linux/serial.h>
  #include <asm-generic/ioctls.h>
  #include <gpio.h>

  #include <QPixmap>
  #include <QMovie>



   // Класс заставки
 class Splash : public QObject {
Q_OBJECT
public:
Splash() {
    this->processLabel = new QLabel();

    connect(&_timer, SIGNAL(timeout()), this, SLOT(emitFinished()));
}
// Показываем заставку и стартуем таймер
void start() {
    movie = new QMovie("./image/Titul.gif");

    processLabel->setText("Splash Screen");

    processLabel->resize(640,480);

    processLabel->setMovie(movie);

    processLabel->setWindowFlags(Qt::FramelessWindowHint);

    processLabel->setAlignment(Qt::AlignCenter);

    processLabel->setGeometry(  QStyle::alignedRect(Qt::LeftToRight,Qt::AlignCenter,processLabel->size(),qApp->desktop()->availableGeometry())         );

    movie->start();

    processLabel->show();

    _timer.start(5000);
}
 signals:
// Сигнал завершения работы заставки
void finished();

 private slots:
 void emitFinished() {
    processLabel->deleteLater();

    movie->deleteLater();

    emit finished();
}

 private:
  QLabel *processLabel;

QMovie *movie;

QTimer _timer;
};

#include "main.moc"

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

QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));

QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));

QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

QTextCodec::setCodecForTr( QTextCodec::codecForName("UTF-8"));

// настройка ножек для RS232 порта 1
 Gpio gpio;

 gpio.open(76);
 gpio.set_direction(76,1);
 gpio.set_value(76,0);

 gpio.open(77);
 gpio.set_direction(77,1);
 gpio.set_value(77,1);

 gpio.open(78);
 gpio.set_direction(78,1);
 gpio.set_value(78,1);

 gpio.open(79);
 gpio.set_direction(79,1);
 gpio.set_value(79,1);

 // порт 2
 gpio.open(68);
 gpio.set_direction(68,1);
 gpio.set_value(68,0);

 gpio.open(69);
 gpio.set_direction(69,1);
 gpio.set_value(69,1);

 gpio.open(70);
 gpio.set_direction(70,1);
 gpio.set_value(70,1);

 gpio.open(71);
 gpio.set_direction(71,1);
 gpio.set_value(71,1);


struct serial_rs485 rs485conf;
int fd = open ("/dev/ttyAPP1", O_RDWR);
if (fd < 0) {
        qDebug()<<"rror: Can't open: /dev/ttySP0";
}

if (ioctl (fd, TIOCGRS485, &rs485conf) < 0) {
        qDebug()<<"Error: TIOCGRS485 ioctl not supported";
}

rs485conf.flags |= SER_RS485_ENABLED;

rs485conf.delay_rts_before_send = 100;

rs485conf.delay_rts_after_send = 100;

if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
        qDebug()<<"Error: TIOCSRS485 ioctl not supported.";
}

MainWindow w;

SoftKeyBoardContext * ic = new SoftKeyBoardContext();

a.setInputContext(ic);

w.setWindowFlags(Qt::FramelessWindowHint);

Splash splash;

splash.start();

QObject::connect(&splash, SIGNAL(finished()), &w, SLOT(show()));

return a.exec();

}

Собрал без ошибок. Программа падает при переходи на 'processLabel->deleteLater();'.


Ответы (1 шт):

Автор решения: Alexander Chernin

Попробуйте так (Qt 5.4+):

MainWindow w;
...

QTimer::singleShot(5000, [processLabel, movie, &w]() {
    processLabel->deleteLater();
    movie->deleteLater();
    w.show()
});

Или:

QTimer::singleShot(5000, [processLabel, &w]() {
    // Если вы точно знаете, что метка содержит муви
    processLable->movie()->deleteLater();
    processLabel->deleteLater();
    w.show()
});

Тогда второй singleShot не нужен.

Дополнение для "древних" версий Qt. Файл main.cpp

// Класс заставки
class Splash : public QObject {
    Q_OBJECT
public:
    Splash() {
        this->processLabel = new QLabel();
        connect(&_timer, SIGNAL(timeout()), this, SLOT(emitFinished()));
    }
    // Показываем заставку и стартуем таймер
    void start() {
        processLabel->setText("Splash Screen");
        processLabel->resize(640,480);
        processLabel->setWindowFlags(Qt::FramelessWindowHint);
        processLabel->setAlignment(Qt::AlignCenter);
        processLabel->setMovie(...)
        processLabel->show();
        _timer.start(5000);
    }
signals:
    // Сигнал завершения работы заставки
    void finished();
private slots:
    void emitFinished() {
        processLabel->deleteLater();
        movie->deleteLater();
        emit finished();
    }
private:
    QLabel *processLabel;
    QMovie *movie;
    QTimer _timer;
};

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

    MainWindow w;

    Splash splash;
    splash.start();
    QObject::connect(&splash, SIGNAL(finished()), &w, SLOT(show()));

    return a.exec();
}

// Если класс Splash объявлен в main.cpp, то надо подключить `moc`-файл
// Не забудьте после этого выполнить команду `qmake`
#include "main.moc"
→ Ссылка