Загрузка тяжелого файла через StackView
Добрый день!
При загрузке файла qml через StackView, приложение зависает и через некоторое время переходит на нужную страницу. Поставил BusyIndicator и попробовал сделать через Loader. Все работает: нажимаешь, появляется BusyIndicator, затем переходит на следующую страницу:
main.qml:
ApplicationWindow { id: window visible: true width: 640 height: 480 Loader { anchors.fill: parent id: loader active: true asynchronous: true } BusyIndicator { id: busyIndicator anchors.centerIn: parent running: loader.status == Loader.Loading ? true : false }
Так же есть две кнопки:
Button { id:btn1 text: qsTr("Назад") onClicked: stackView.pop() } Button { id:btn2 text: qsTr("В начало") onClicked: stackView.push(homePage) }
и сама страница:
HomePageForm { TitleRect.onAppClicked: { stackView.push(loader) loader.source = "8/HomePage.qml" } }
После нажатия кнопки btn2 из любой части программы, переходишь на homePage. Нажимаешь повторно TitleRect для перехода к файлу qml, пишет :
QML StackView: push: nothing to push
Не пойму, что я делаю не так.
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.Do you like it? Share on social networks!
- Akiv Doros
- Nov. 11, 2024, 2:58 p.m.
C ++ - Test 004. Pointers, Arrays and Loops
- Result:50points,
- Rating points-4
- molni99
- Oct. 26, 2024, 1:37 a.m.
C ++ - Test 004. Pointers, Arrays and Loops
- Result:80points,
- Rating points4
- molni99
- Oct. 26, 2024, 1:29 a.m.
C ++ - Test 004. Pointers, Arrays and Loops
- Result:20points,
- Rating points-10
Добрый день.
Проблема в том, что StackView при выполнении метода pop уничтожает тот объект, который был в него добавлен через метод push() . В документации этот момент прописан.
Вам нужно создавать объект homePage каждый раз перед тем, как вы будете добавлять его в StackView через push.
Я немного не понял. При нажатии кнопки btn2 я попадаю на homePage, с этим проблем нет. Однако, на homePage расположена кнопка для перехода в папку 8, на страницу HomePage.qml Так вот при нажатии на эту кнопку выдает ошибку QML StackView: push: nothing to push
А где находится в коде stackView относительно loader?
Они оба в main.qml
Может всё-таки более подробный код покажите?
main.qml
Кажется знаю, в чём проблема. StackView по умолчанию должен содержать минимум один объект, если объектов больше 1, то метод pop удаляет последний компонент, если только один то он не удаляется. В вашем случае вы уже добавили loader, поэтому метод push не имеет эффекта, поскольку объект уже в стеке. При чём видимо в самом начале.
В общем напишите код так, чтобы homePage был в стеке в самом начала на уровне 1, а остальное просто добавляйте или удаляйте. Если у вам есть ещё тяжёлые объекты, то добавьте ещё один свой loader для тех страниц и перезагружайте через тот, что уже есть. Нужно с чем-то одним определиться вам.
Вот код, демонстрирующий проблему.
Положил loader в homePage. Все работает как надо, спасибо. Теперь проблема с busyIndicator. Положил его вместе с loader. Теперь при загрузке большого файла просто темный экран. В чем может быть проблема?
Я бы этот индикатор оставил снаружи в окне приложения и запускал его через обработку сигнала о загрузке от лоадера.
Да, я примерно так и сделал. Разместил его в main.qml:
Получается он запускается и работает постоянно. Или я ни от того сигнала запускаю loader?
Вот кусок документации на Loader
Я думаю, что Вы можете внутри компонента делать проверку на статус лоадера и по изменению его статуса переопределять состояние индикатора, который находится снаружи компонента.
Пожалуй, это должно выглядеть примерно так
Евгений, огромное спасибо, все работает!
Добрый день! Еще один вопрос по работе louder. stackView.currentItem.title показывает в заголовке title страницы.
Переходя на страницу через loader:
title HomePage.qml не показывает, выдает ошибку: Unable to assign [undefined] to QString
У лоудера есть свойство SetSourse. Пробовать через него?
Добрый день! Содержимое HomePage.qml покажите. Подозреваю, что у него или нет title или нужно alias на этот title делать.
ну понятно, в случае лоадера вы не получите доступ к title так, как делаете. Лоадер выступает в качестве промежутоного звена, тем более, что вы его пушите в StackView, чтобы достучаться до той property, нужно писать так
Как вариант, можно попробовать немного кастомизировать Loader, чтобы он отвечал вашему изначальному коду. То есть создаёте новый QML файл - CustomLoader.qml
CustomLoader.qml
А в нём уже сделать property alias и заменить таким кастомным лоадером стандартный.
Тогда по идее Loader будет реализовывать ваш обобщённый интерфейс и следующий код должен будет работать.
Ошибка:
qrc:/CustomLoader.qml:4 Invalid alias reference. Unable to find id "item"
мда.. я как-то не подумал, что QML делает alias только по id, хотя логично.. а item это не id, а property.
Ну тогда нужно слушать изменение currentItem у StackView и по его изменению реализовывать специфичную логику. Выглядеть может так.
Прокомментирую код выше.
Ну и для каждой страницы нужно реализовывать эту функцию соответсвующим образом, чтобы был единообразный интерфейс QML объекта.
Интрересно. А если сделать вообще без лоудера, через stackView загружать страницу:
Только непонятно к какому свойству stackView привязать busyIndicator, что бы он запускался во время загрузки тяжелого файла? В этом случае, проблемы с заголовками нет.
По моему опыту без лоадера чисто на StackView либо не получится, либо будет с очень большими костылями. StackView служит для организации структуры контента, но не для асинхронной загрузки.
Но есть немного иной вариант, вы довольно близко находитесь со своей идеей в этом последнем коде
Сделайте так, но в HomePage поместите loader и busyIndicator. Внутрь лоадера поместите тяжёлую часть файла. Таким образом при помещении файла HomePage.qml внутрь StackView, часть контента, которая лёгкая, отобразится сразу, а тяжёлую часть начните загружать через лоадер в обработчике Component.onCompleted
HomePage.qml
Попробуем идти в другую сторону.
Возможно не засовывать в stackView loader, а при нажатии на TitleRect сразу обращаться к лоудеру? Файл в папке 8, около 800 страниц. Получается при нажатии сначала все эти 800 страниц скачиваются в кеш, а только потом осуществляется переход на HomePage. Затем переходы занимают 1-2 сек и внутри, и с главной страницы приложения. Конечно это неудобно. На слабых устройствах загрузка занимает порядка 2 минут.
какие 800 страниц? я допустим понятия не имею, что вы туда загружаете.
Что касается лоадера и stackView. Сделать-то это можно, только не понятно какой вы результат ожидаете. Если вам нужны странички в стиле как у Андроида, то нужен StackView. Это наиболее удобно в данном случае.