LINUX.ORG.RU

Как в QML StackView отследить момент его создания?

 , ,


0

1

У меня все экраны QML-приложения уложены в «основной» объект типа StackView.

Возникла задача запоминать, какой экран был при выключении приложения, и восстанавливать его при включении. Для простоты можно считать, что что есть первый экран «меню» (это initialItem), и из него возможен переход на экран «режим1» или на экран «режим2». Таким образом, после создания StackView, по сути надо сделать одну-единственную команду, например:

stackView.push( mode1StackComponent );

Проблема в том, что я не могу понять в как и в каком месте кода отловить момент создания экрана «меню», чтобы выполнить эту команду. Код примерно такой:
    StackView {
        id: stackView

        anchors.fill: parent
        focus: true
        initialItem: mainMenuStackComponent

        // Окно с основным меню
        Component {
            id: mainMenuStackComponent

            MainMenu {
                id: mainMenu
                enabled: Stack.status === Stack.Active
            }
        }

        // Окно режима 1
        Component {
            id: mode1StackComponent

            Mode1 {
                id: mode1
                enabled: Stack.status === Stack.Active
            }
        }

        // Окно режима 2
        Component {
            id: mode2StackComponent

            Mode2 {
                id: mode2
                enabled: Stack.status === Stack.Active
            }
        }
    }

Я пробовал добавлять код:
Component.onCompleted: {
    stackView.push( mode1StackComponent );
    console.warn("Auto call");
}

В блок с id:mainMenu, но тогда появляется ошибка:
qml: Warning: StackView: You cannot push/pop recursively!
__recursionGuard (file:///opt/qt_5_11_2/5.11.2/gcc_64/qml/QtQuick/Controls/StackView.qml:791)
push (file:///opt/qt_5_11_2/5.11.2/gcc_64/qml/QtQuick/Controls/StackView.qml:568)
onCompleted (qrc:/qmlCode/main.qml:77)
__loadElement (file:///opt/qt_5_11_2/5.11.2/gcc_64/qml/QtQuick/Controls/StackView.qml:825)
__performTransition (file:///opt/qt_5_11_2/5.11.2/gcc_64/qml/QtQuick/Controls/StackView.qml:911)
push (file:///opt/qt_5_11_2/5.11.2/gcc_64/qml/QtQuick/Controls/StackView.qml:605)
expression for onCompleted (file:///opt/qt_5_11_2/5.11.2/gcc_64/qml/QtQuick/Controls/StackView.qml:777)
qml: Auto call

Видимо, это связано с тем, что onCompleted() в QML не гарантирует создания подчиненных элементов к моменту своего срабатывания.

Поэтому не могу сообразить, как еще можно сделать автоматическое открытие «окна второго уровня» в StackView с помещением базового окна «меню» в стек.

★★★★★

Последнее исправление: Xintrea (всего исправлений: 2)

initialItem: mainMenuStackComponent

Попробуй вызывать добавление в Component.onCompleted элемента mainMenuStackComponent. Я с таким сталкивался, но не помню точного решения.

ox55ff ★★★★★
()
Ответ на: комментарий от ox55ff

Попробуй вызывать добавление в Component.onCompleted элемента mainMenuStackComponent.

Тогда появляется ошибка:

qrc:/qmlCode/main.qml:71 Component elements may not contain properties other than id

А если вставить в id:stackView, то будет просто сегфолт.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Как оно вообще у тебя запустилось:

stackView.push( mode1 );

ведь такого id (mode1) не существует в цепочке компонентов main menu.

Dendy ★★★★★
()
Ответ на: комментарий от Dendy

Извиняюсь, конечно там mode1StackComponent. Я просто пример упрощал чтобы на форум добавить. В реальности там другие названия элементов.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

А вне куемеля ты не можешь дождаться когда вьюха вся проинитится как тебе надо и потом дернуть что нужно?

Видимо, придется так сделать, потому что если всунуть автовызов в id:stackView, сегфолт происходит из-за того, что начинают инититься C++-ные объекты, используемые в окне второго уровня до того, как проинициализировались объекты окна первого уровня.

Xintrea ★★★★★
() автор топика
Последнее исправление: Xintrea (всего исправлений: 1)
Ответ на: комментарий от Xintrea

начинают инититься C++-ные объекты...

Для тебя не должно быть важным как именно и что там под капотом культи происходит. Оно на то и фреймворк. Всегда абстрагируйся. Я бы вообще не писал никакой логики в куемеле, а писал бы всю снедь уже в плюсах.

Представь это как бекенд и фронт. В бекенде вся работа, а фронт это тупая шкурка, которая может только слушать что ей бекенд говорит и пересылает действия пользователя бекенду в удобоваримой ему (бекенду) форме.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Я читал ровно противоположное утверждение что QML-это все, а на С++ надо писать обслуживающий QML-код, то есть модели да контроллеры.

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

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

на С++ надо писать обслуживающий QML-код, то есть модели да контроллеры

Модели и контроллеры это и есть «бекенд». Только, оно не должно обслуживать, оно должно быть самостоятельным. А «вьюха», на то она и вьюха, что только отображает состояние бекенда, да пользаку кнопочки предоставляет.

Вот цитата из того треда:

и используем для отрисовки интерфейсов

Ты понял категорично, да не в ту сторону. Вьюха получает данные от моделек. Да, вроде как модель может быть воспринята второстепенной. Но она не может быть второстепенной. Это как панель приборов и движок. Что важнее, панель приборов (вьюха) или движок (бекенд)?

deep-purple ★★★★★
()
Последнее исправление: deep-purple (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.