Russian Qt Forum

Qt => Qt Quick => Тема начата: lighting от Февраль 05, 2013, 17:10



Название: Динамическое создание объектов
Отправлено: lighting от Февраль 05, 2013, 17:10
Пробовал создавать объекты в QML динамически, из js файла как в примере samegame. В целом все получилось, но возникла одна проблема которую никак не придумаю как обойти.
Создаю объект из следующего qml файла
Код
Javascript
import QtQuick 1.1
import "../../worker.js" as Worker
 
Item {
   id: base
   property bool selected: false;
   property int index: 0
   width: childrenRect.width
   height: childrenRect.height
   Rectangle {
       anchors.fill: caption
       color: "transparent"
       visible: selected
       border {color: "steelblue"; width: 2}
   }
   Text {
       id: caption
       color: "white"
   }
   MouseArea {
       id: mouseArea
       anchors.fill: parent
       onPressed: Worker.changeSelection(base.index);
   }
}
 
глобальные переменные JavaScript файла
var maxIndex = 10;
var labels = new Array(maxIndex);  //массив хранящий динамически созданные объекты

Функция в которой создаются объекты:
Код
Javascript
function addLabel(text) {
   var component;
   for (var i = 0; i < maxIndex; i++)
       if (labels[i] == null)
       {
           component = Qt.createComponent("TextLabel.qml");
           if (component.status == Component.Ready)
           {
               var dynamicObject = component.createObject(editPage);
               if (dynamicObject == null) {
                   console.log("error creating label", component.errorString());
                   return false;
               }
               dynamicObject.selected = false;
               dynamicObject.x = editPage.width/2;
               dynamicObject.y = editPage.height/20;
               dynamicObject.text = text;
               dynamicObject.index = i;
 
           } else {
               console.log("error loading block component", component.errorString());
               return false;
           }
           labels[i] = dynamicObject;
           return true;
       }
}

Функция которая вызывается по событию из созданного объекта
Код
Javascript
function changeSelection(index) {
   if (selectedLabelIndex == -1) labels[index].selected = true;
...
}
Проблема заключается в следующем - если вызывать changeSelection() из js файла или main.qml то все работает нормально, но в случае если вызвать ее из созданного объекта (onPressed: Worker.changeSelection(base.index);) то получаю сообщение об ошибке labels[index] - undefined.
Насколько я понял проблема возникла из-за того что объекты хранящиеся в labels создавались внутри addLabel() и т.к. они создавались с помощью  Qt.createComponent() то им присвоился контекст addLabel() который был по выходу из функции удален и соответственно глобальную переменную labels в их контексте уже не видно. Собственно вопрос - как сменить контекст для создаваемых объектов чтобы labels в нем был виден.


Название: Re: Динамическое создание объектов
Отправлено: twp от Февраль 10, 2013, 13:55
а можно выложить архив с кодом чтоб самому попробовать?


Название: Re: Динамическое создание объектов
Отправлено: lighting от Февраль 12, 2013, 14:38
извини за задержку, вот проект. Замысел был в том чтобы можно было добавлять Label, по щелчку выделялся конкретный экземпляр, после чего его можно было бы таскать по всей форме, но пока-что это не получается.


Название: Re: Динамическое создание объектов
Отправлено: twp от Февраль 12, 2013, 22:52
В общем основная проблема в том, что JS скрипт Worker было объявлен и в main.qml и в TextLabel.qml что в итоге привело к тому, что у каждого был свой экземпляр Worker. Я немного подправил твой пример, убрал Worker из TextLabel.qml и добавил ему сигнал clicked(). При создании объекта TextLabel этот сигнал динамически коннектится со слотом onLabelClicked() из в main.qml и уже в нем происходит передача индекса TextLabel в Worker.changeSelection(). Там же установливается цель для перетаскивания, поскольку такой биндинг не работает
Код
Javascript
drag.target: Worker.selectedLabel == null ? test : Worker.selectedLabel
 
скорее всего потому что Worker не QML объект и соответсвенно selectedLabel не является свойством QML объекта
Там еще осталась проблема с перетаскиванием - TextLabel таскается только когда кликаешь вне ее области


Название: Re: Динамическое создание объектов
Отправлено: lighting от Февраль 13, 2013, 13:24
twp спасибо за подсказку, я искал да не там. Никак не думал что у меня  будет два ( и даже больше) экземпляра Worker.
Биндинг не получается скорее всего из-за того что нет сигнала, указывающего что Worker.selectedLabel изменился. Ну а проблема с перетаскиванием это мелочь, в лоб можно решать так
Код
Javascript
   MouseArea {
...
       enabled: !selected
...
   }
в TextLabel, ну или поэлегантнее способ найти.


Название: Re: Динамическое создание объектов
Отправлено: twp от Февраль 13, 2013, 22:52
twp спасибо за подсказку, я искал да не там. Никак не думал что у меня  будет два ( и даже больше) экземпляра Worker.
А отладчиком пользовался? Это довольно легко определить, если поставить точки останова в функциях Worker. Отладчик сразу показывает количество labels, а оно разное для main.qml и TextLabel.qml


Название: Re: Динамическое создание объектов
Отправлено: lighting от Февраль 14, 2013, 09:57
В QML я пока-что отлаживал только с помощью console.log  видимо надо переходить к более действенным инструментам.