Запуск основной программы после закрытия заставки

Использую достаточно медленный ARM контроллер. Поднял на нем линукс.

Перед запуском основной программы появляется заставка на 5 секунд. После происходит загрузка. Понятно что гиф анимация требует достаточно ресурсов ЦПУ, которых и так нет.

Проблема заключается в одновременном запуски конструктора и окна "mainwindow" и гиф анимации. Охота разделить их во времени, чтобы сначала была гиф анимация после запуск конструктора окна "mainwindow" и переход на основную программу.

Вот код, что сделал:

// Класс заставки
class Splash : public QObject {
    Q_OBJECT
public:
    Splash() {
        processLabel = new QLabel();
        connect(&_timer, SIGNAL(timeout()), this, SLOT(emitFinished()));
        connect(&_temerMainWindow, SIGNAL(timeout()), this, SLOT(emitShowMainWindow()));
    }

    // Показываем заставку и стартуем таймер
    void start() {
        movie = new QMovie("./image/Titul.gif");
        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();
        _temerMainWindow.start(4500);
        _timer.start(5000);
    }
signals:
    // Сигнал завершения работы заставки
    void finished();
private slots:
    void emitFinished()
    {
        movie->stop();
        movie->deleteLater();
        processLabel->deleteLater();
       _timer.stop();
    }

    void emitShowMainWindow()
    {
        _temerMainWindow.stop();
        MainWindow w;  // Не хочет запускать окно MainWindow программа падает. В чем дело?
        w.setWindowFlags(Qt::FramelessWindowHint);
        w.show();
        emit finished();
    }

private:
    QLabel *processLabel;
    QMovie *movie;
    QTimer _timer;
    QTimer _temerMainWindow;
};

#include "main.moc"

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

    Splash splash;
    splash.start();

    return a.exec();
}

Программа падает при вызове окна 'MainWindow'.


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

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

Ваш объект окна создается в локальной (стековой) памяти метода, поэтому когда метод завершает свою работу, то вся локальная память очищается, следовательно удаляется объект окна. Я предлагаю сделать немного по-другому.

Минимальный рабочий вариант с применением QEvenLoop:

#include "mainwindow.h"

#include <QApplication>
#include <QLabel>
#include <QMovie>
#include <QStyle>
#include <QTimer>
#include <QDesktopWidget>
#include <QEventLoop>

// Класс заставки
class Splash : public QObject {
    Q_OBJECT
public:
    Splash() :QObject() {
    }

    // Показываем заставку и стартуем таймер
    int exec() {
        // Класс QEventLoop нам нужен для создания локального бесконечного цикла  сообщений, запускаемого методом QEventLoop::exec(), в самом конце метода
        QEventLoop _loop;

        // Объекты movie и processLabel удалятся автоматически при завершении работы метода
        QMovie movie("./image/Titul.gif");
        QLabel processLabel;
        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, &_loop, SLOT(quit()));

        // Метод _loop.exec() не завершит свою работу до тех пор, пока 
        // _loop не получит сигнал quit() (от таймера)
        return _loop.exec();
    }

};

#include "main.moc"

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

    // Заставку создаем через указатель, чтобы после удалить его за ненадобностью и освободить память
    Splash* splash = new Splash();

    // Создаем и показываем заставку. Метод exec будет работать пока не получит сигнал
    // от внутреннего таймера о завершении цикла и выходе из него
    splash->exec();

    // Удаляем объект заставки - очищаем память
    splash->deleteLater();

    // Показываем главное окно приложения
    MainWindow window;
    window.show();

    return a.exec();
}

Дополнение 1. Попытка избавления от "зеленого":

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

    MainWindow window;
    Splash* splash = new Splash();      
    splash->exec();    
    window.show();
    splash->deleteLater();    

    return a.exec();
}

Дополнение 2. Чуть более сложный вариант избавления от зеленого экрана

// Класс заставки
class Splash : public QObject {
    Q_OBJECT
public:
    Splash():
        movie("./image/Titul.gif")
    {
    }

    // Показываем заставку и стартуем таймер
    int exec() {
        // из метки и муви делаем поля класса
        // остальное оставляем как было

        // ...
    }

private:
    QMovie movie;
    QLabel processLabel;
};

#include "main.moc"

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

    Splash* splash = new Splash();
    splash->exec();

    MainWindow window;
    window.show();
    // Теперь у вас на экране должны быть и заставка, и окно

    // Следующая строка должна заставку скрыть и удалить
    splash->deleteLater();

    return a.exec();
}
→ Ссылка