Как передать «это» из элемента QML в функцию JS

Подобно ключевому слову this в C++, я хотел бы либо иметь элемент QML для передачи себя в функцию JS, либо установить свойство другого элемента для себя. Это возможно?

Например:

Rectangle{
id:theParent

property var theElement

SomeElement{
id:theChild
   MouseArea {
        anchors.fill:parent
        onClicked: {
            someJsFunction(*whatGoesHere*)
            parent.theElement=*whatGoesHere*
        }
    }

Или, подумайте об этом:

Rectangle{
id:theParent

property var theElement

SomeElement{
id:theChild
    }

Затем в SomeElement.qml:

Rectangle{
   MouseArea {
        anchors.fill:parent
        onClicked: {
            someJsFunction(*whatGoesHere*)
            parent.theElement=*whatGoesHere*
        }
}
}

В этом случае *whatGoesHere* будет экземпляром SomeElement, из которого они вызываются.

Возможно ли это в QML? Я бы подумал, что свойство id имеет смысл, но, согласно документации, вы не можете запросить значение поля id, и в любом случае id не будет доступно, если мой SomeElement будет описан в отдельном файле, а обработка whatGoesHere появилась в этом отдельном файле, а не в конкретном экземпляре.


person johnbakers    schedule 05.11.2013    source источник


Ответы (3)


У меня есть два взаимодополняющих предложения:

Во-первых, для одноразового использования передайте идентификатор, так как это в основном указатель на элемент:

MouseArea {
    id: myClicker;
    onClicked: { callFunc (myClicker); }
}

Затем, если вам нужно несколько элементов для совместного использования этого поведения, это означает, что вы используете MVC, поэтому идентификатор будет работать точно так же:

Repeater {
    model: 100;
    delegate: MouseArea {
         id: myClicker;
         onClicked: { callFunc (myClicker); }
    }
}

Это классическая часть.

Но чтобы сделать еще лучше, если вы создаете свои собственные компоненты, не забудьте создать вспомогательное свойство «я», которое правильно выполняет «эту» работу:

MouseArea { // component root definition
    id: base;

    property var self : base; // bind self on the I
}

Затем используйте его следующим образом:

Repeater {
    model: 100;
    delegate: MyComponent {
         onClicked: { callFunc (self); }
    }
}

Используйте это так часто, как вы хотите!

person TheBootroo    schedule 12.11.2013
comment
Хорошие решения, есть ли у вас рекомендации для компонентов, определенных на С++ и выставленных через qmlRegisterType()? Можно ли использовать QObject* с типом Q_PROPERTY, указывающим на this? - person Ayberk Özgür; 28.06.2016

Экземпляром вашего SomeElement является значение свойства id, то есть theChild. Вы можете использовать его как this. Насколько я могу судить, другого встроенного способа не существует. Но вы можете попробовать добавить свою собственную иерархию элементов QML со свойством, которое будет возвращать this.

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

person ixSci    schedule 05.11.2013
comment
Предположим, у меня много SomeElement, и я хочу, чтобы эта функциональность была определена в SomeElement.qml, а не в строке, как в моем коде. Тогда id будет недоступен внутри SomeElement.qml, поскольку он не является экземпляром (пока). - person johnbakers; 05.11.2013
comment
Добавьте имя к каждому SomeElement, получите дочерние элементы родителя (который содержит эти SomeElement) и найдите то, что вам нужно, по имени. Тогда используйте. Это очень просто - person ixSci; 05.11.2013
comment
Конечно, циклический просмотр всех дочерних элементов родителя — один из способов сделать это, но я надеялся на прямой доступ в соответствии с подразумеваемым поведением моего кода выше. Но я подозреваю, что это не идиоматично в QML - person johnbakers; 05.11.2013

Если вы определяете свой элемент в отдельном файле, вы можете просто назначить id и использовать его. Он будет действителен только в контексте этого экземпляра:

SomeElement.qml

Rectangle{
   id: thisElement
   MouseArea {
        anchors.fill: parent
        onClicked: {
            someJsFunction(thisElement);
            parent.theElement = thisElement;
        }
   }
}
person TheHuge_    schedule 06.11.2013
comment
Если у вас есть несколько SomeElements в другом файле, несколько экземпляров, каждый будет иметь свой собственный идентификатор. Вы говорите, что onClicked достаточно умен, чтобы заменить thisElement, который у вас есть в файле SomeElement.qml, идентификатором возможного экземпляра, установленным в другом файле? - person johnbakers; 07.11.2013
comment
Это ничего не заменит: подумайте о двух идентификаторах как о двух указателях, указывающих на один и тот же объект. - person TheHuge_; 07.11.2013