g
Aug. 23, 2019, 9:35 p.m.

QQmlApplicationEngine::loadData() в Release сборке

QQmlApplicationEngine, release

Возникла проблема с запуском QML-приложения (Qt 5.12.2( mingw 7.3 32-bit )/ Windows-8 64-bit).
Создал приложение из примера Qt\Examples\Qt-5.12.2\quick\layouts\ :

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDir>
#include <QFile>
#include <QResource>
#include <QByteArray>
#include <iostream>

void exploreQrcDir( const QString& path )
{
    QDir qrcDir( ":/layouts" );
    std::cout << ":/layouts : " << std::endl;
    for ( const QString& item : qrcDir.entryList())
    {
        std::cout << item.toStdString() << std::endl;
    }

    for ( const QFileInfo& item : qrcDir.entryInfoList())
    {
        std::cout << item.absoluteFilePath().toStdString() << ";" << item.isReadable() << std::endl;
    }
}

QByteArray resourceData( const QString& path )
{
    QResource qmlFile( path );

    std::cout << "Resource is valid = " << qmlFile.isValid()
              << " , is compressed = " << qmlFile.isCompressed()
              << " , size = " << qmlFile.size() << std::endl;

    QByteArray data = (const char*)( qmlFile.data() );
    std::cout << "Resource data = " << qmlFile.data() << std::endl;
    std::cout << "ByteArray = " << data.toStdString() << std::endl;

    return data;
}

int main(int argc, char* argv[])
{
    QGuiApplication app(argc, argv);

    exploreQrcDir( ":/layouts" );

    const QString qmlDataSource( "qrc:/layouts/layouts.qml" );
    QQmlApplicationEngine engine;

    engine.loadData( resourceData( ":/layouts/layouts.qml" ) ); //     debug version - ok
                                                                // release version - qml window not open

//    engine.load( qmlDataSource );  // ok
//    engine.load( QUrl( qmlDataSource ) ); // ok

    return app.exec();
}

В результате в debug-версии работает любой вариант.
А в release-версии - приложение виснет на engine.loadData().
Ни сообщений об ошибке, ни окна приложения, ничего. Только процесс висит.

Вопрос: как гарантированно загрузить qml-файл из ресурсов приложения?

3

Do you like it? Share on social networks!

7
R
  • Aug. 23, 2019, 10:45 p.m.

так а оригінальник код збираєтсья і запускає?
цей

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:///layouts/layouts.qml")));
    g
    • Aug. 23, 2019, 11:35 p.m.

    Ну там-же в комментариях написано, что при значении qmlDataSource = qrc:/layouts/layouts.qml стандартный подход работает.
    Он меня не устраивает - нет результата выполнения загрузки.
    Можно конечно после загрузки делать проверку: !engine.rootObjects().isEmpty().

    Собственно вопрос с загрузкой QML-файла из ресурса возник в другом проекте, а этот я взял чтобы найти алтернативный вариант.
    И получил неожиданность.

      R
      • Aug. 23, 2019, 11:48 p.m.

      чесно не розумію навіщо вам перевіряти чи завантажився базовий QML но якщо не принцепово, можна через базову сторінку грузити Loader
      і статус перевіряти, а файли передавати через пропертю

                          Loader{
                              id: loader
                              focus: true
                              asynchronous: true
                              source: ""
                              width: parent.width
                              height: parent.height
                              onStatusChanged:{
                                  if (loader.status === Loader.Ready)
                                  {
      
                                  }
                              }
                          }
      
        g
        • Aug. 24, 2019, 12:34 a.m.

        Начнем с начала: есть большой проект ( я дорабатываю и поддерживаю ), больше 100 QML-файлов с подпроектми. Сборка идет 25-30 минут. Все это работает уже несколько лет.
        При переходе на более свежую версию Qt обратил внимание, что на некоторых машинах release-версия приложения стартует, но главное окно не открывается. Путем расширенного вывода в лог вычислено место - QQmlApplicationEngine::load( "qrc:/main.qml" ), после которого engine.rootObjects() дает пустой список.
        Подчеркиваю - на некоторых машинах. Например - две копии одной виртуальной машины. Разница - на одной собирается проект, на другой - нет.
        Библиотеки везде одинаковые ( собраны windeployqt в одно место ).
        Отсюда и вырос тестовый проект из примера.
        Вопрос: откуда и почему не грузится main.qml в release-версии?
        Я не хочу обойти проблему. Я хочу ее решить.

          Evgenii Legotckoi
          • Aug. 24, 2019, 1:55 a.m.
          • (edited)

          Не знаю, в чём конкретно у вас проблема на ваших машинах, но если вы запустили конкретно пример layouts и ничего не менялм в pro файле, то проблема в release версим конкретно здесь в этих строчках.

          target.path = $$[QT_INSTALL_EXAMPLES]/quick/layouts
          INSTALLS += target
          

          Стоит только их закомментировать, как в release версии ваша ошибка не проявляется.

          По сути проблема в том, что debug версия находит другие относительные пути для :/layouts/layouts.qml , в отличие от qrc:///layouts/layouts.qml .

          Возможно, что в данном конкретном случае debug версия проверяет файлы относительно каталога сборки, а release относительно места установки, в котором оказывается пусто. Вообще, если у вас всё собирается в испольняемый файл, без компиляции внешних ресурсов RCC, то обязатльно нужно использовать префикс qrc:// . Это правильно. Если же используете внешние ресурсы RCC, то нужно указывать относительный путь и чтобы этот файл там был.

          По сути, непонятно по какой причине, у вас на некоторых машинах не находится правильно путь к ресурсам. Можете попробовать собирать в RCC и класть рядом с исполняемым файлом, и соответсвенно указывать путь к RCC относительно исполняемого файла. Это должно гарантированно решить вашу проблему. Если останутся нерабочие машины, то тогда писать на багтрекер Qt.

            g
            • Aug. 24, 2019, 12:06 p.m.

            Шикарный ответ. Огромное спасибо. Буду пробовать.

            Дополнительный вопрос ( возникла мысль, но не проверял ) - что будет с загузкой qml-файла, если он ссылается на недоступный qml-файл?
            Приложение будет бросать какие-то сообщения или будет молча не загрузиться?

              Evgenii Legotckoi
              • Aug. 24, 2019, 5:21 p.m.
              • (edited)

              Не помню, давно уже с QML не работал, по-моему, обычно пишет в консоль, что не находит файл. В любом случае какую-то ошибку в консоль выкидывает.

              Но если честно, если у вас проект будет аккуратно разработан, а также все QML файлы будут в ресурсах, то проблемы такой возникать не должно.

                Comments

                Only authorized users can post comments.
                Please, Log in or Sign up
                • Last comments
                • AK
                  April 24, 2025, 12:04 p.m.
                  UPD: Переписал логику воспроизведения через стороннюю библиотеку BASS. Там выбрать можно
                • Evgenii Legotckoi
                  April 16, 2025, 5:08 p.m.
                  Благодарю за отзыв. И вам желаю всяческих успехов!
                • IscanderChe
                  April 12, 2025, 5:12 p.m.
                  Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
                • AK
                  April 1, 2025, 11:41 a.m.
                  Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
                • Evgenii Legotckoi
                  March 9, 2025, 9:02 p.m.
                  К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…