LINUX.ORG.RU

Почему в QML нельзя задавать свойства для типа Component и как это обойти?

 , component


0

1

Есть у меня приложение, которое состоит из страниц. Страницы оформлены в виде типов Component. Страницы объединены в StackView, через него я их и переключаю.

Есть страница fileSelectDialogComponent, которая представляет из себя самодельный виджет выбора файла:

    // Объединение страниц интерфейса в структуру StackView для возможности переключения между ними
    StackView {
        id: stackView

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

            MainMenu {
                id: mainMenu
                anchors.fill: parent
                enabled: Stack.status === Stack.Active
            }
        }
...
        // Страница с виджетом выбора файла
        Component {
            id: fileSelectDialogComponent

            FileSelect {
                id: fileSelectDialog
                anchors.fill: parent
                enabled: Stack.status === Stack.Active
            }
        }

Вызывается эта страница так:
    // Выбор файла
    Connections {
        target: fileSelectButton
        onClicked: stackView.push( fileSelectDialogComponent )
    }

Вопрос в том, каким образом передать имя выбранного файла из страницы fileSelectDialogComponent в страницу mainMenuStackComponent. Причем предать это дело локально, а не через глобальный объект.

Проблема в том, что тип Component - это такой странный тип, в котором нельзя создавать свойства. Если я сразу после строки «id: fileSelectDialogComponent» попробую написать:
property alias fileSelectDialog: fileSelectDialog

чтобы «вытащить наружу» виджет FileSelect, то будет ошибка:
qrc:/qmlCode/main.qml:96 Component objects cannot declare new properties.

Так же я не могу достучаться до mainMenu, потому что он находится внутри mainMenuStackComponent, и я так же не могу этот mainMenu вытащить наружу, и не могу в него засунуть имя выбранного файла.

Так же невозможно соединить сигнал-слот так, чтобы сигнал испустился в одном компоненте (выбора файла), и был пойман в слоте компонента, который тоже есть в стеке (основное меню). Неозможно потому, что невозможно связать сигнал-слот, потому что внутрь компонента невозможно влезть, а сам компонент не дает возмжности вывести объекты или их свойства наружу.

Вот. Вопрос: как мне все-таки пробросить данные из одного компонента в другой? Неужели придется делать через глобальную переменную?

★★★★★

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

Ответ на: комментарий от Liferer

Я написал:


Так же невозможно соединить сигнал-слот так, чтобы сигнал испустился в одном компоненте (выбора файла), и был пойман в слоте компонента, который тоже есть в стеке (основное меню). Неозможно потому, что невозможно связать сигнал-слот, потому что внутрь компонента невозможно влезть, а сам компонент не дает возмжности вывести объекты или их свойства наружу.

Xintrea ★★★★★
() автор топика
StackView {
        id: stackView

        property string fileName

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

            MainMenu {
...
                fileName: stackView.fileName
            }
        }
...
        // Страница с виджетом выбора файла
        Component {
            id: fileSelectDialogComponent

            FileSelect {
...
                fileName: stackView.fileName
                onFileSelected: {
                    stackView.fileName = fileName;
                }
            }
        }
tnodir
()
Ответ на: комментарий от tnodir

Коллбековый АД как в жаваскрипте ))

А решение норм.

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

Мда, решение сделать отдельное свойство у StackView (которого у него не должно быть), недалеко ушло от проброса через специально сделанный глобальный объект.

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

Пропустил... Позвольте уточнить, почему используются именно объекты типа Component, а не QML document и почему не используется Loader для отображения временного содержимого?

Liferer
()

Вот пример решения на сигналах (за лишние куски и мусорность прошу не пинать - делал на основе примера из QtCreator):

import QtQuick 2.9
import QtQuick.Controls 2.2

ApplicationWindow {
    id: window
    visible: true
    width: 200
    height: 200
    title: qsTr("Stack")

    Connections {
        target: ldrr.item
        onMessage: ldr.item.text = "Tested"
    }

    Rectangle {
        id: stackView        
        anchors.fill: parent

        Loader {
            id: ldr
            sourceComponent: comp
        }
        Loader {
            id: ldrr
            anchors.top: ldr.bottom
            sourceComponent: compp
        }

        Component {
            id: comp
            Rectangle {
                property alias text: lab.text
                id: recttt
                width: 50
                height: 50
                anchors.left: window.left
                color: "red"
                Label {
                    id: lab
                    text: "default"
                }
            }
        }
        Component {            
            id: compp
            Rectangle {                
                id: rect
                signal message(string str)
                width: 50
                height: 50
                color: "blue"
                anchors.right: window.right
                MouseArea {
                    anchors.fill: parent
                    onClicked: message("Test")
                }
            }
        }
    }
}

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

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