PDA

Просмотр полной версии : возможно ли удаление объекта со stage из другого класса


nelco
20.09.2015, 14:49
в основном классе приложения есть объект (экземпляр класса FloatingCont):



public class Main extends Sprite
{
private var _floatingCont:FloatingCont = new FloatingCont();

public function Main()
{
stage.addChild(_floatingCont);

}

}

пытаюсь из другого класса удалить объект _floatingCont:



public class CodeExamples extends Sprite

{
private var _clickableHeadingExTf:MyButton = new MyButton();


public function CodeExamples()
{

_clickableHeadingExTf.addEventListener(MouseEvent.CLICK, clickListener);
}

private function clickListener(e:MouseEvent):void
{
if (stage.contains(_floatingCont)) {
stage.removeChild(_floatingCont);
}

switch(e.target) {


}

}



}

}



выдаёт ошибку...
получается, что stage.addChild(_ someObject) - работает, stage.removeChildAt(i) - работает, а можно ли как-нибудь сделать stage.removeChild(_someObject) из другого класса?

caseyryan
20.09.2015, 14:55
В другом классе нет ссылки на _floatingCont, соответственно и удалять нечего.
И вообще метод contains вернет true, даже если фактически объект не содержится в самом контейнере, а содержится в каком-то из его дочерних. У contains есть второй параметрб который как раз отключает рекурсивную проверку.
Но вообще лучше не использовать contains, а использовать
if (_floatingCont.parent) _floatingCont.parent.removeChild(_floatingCont);
То есть проверять наличие родителя.

И еще одно. Не надо путать stage и документ класс.
Вначале в Main написано addChild(_floatingCont);
Это совсем не означает, что объект добавился на stage.
addChild(_floatingCont); равнозначно записи this.addChild(_floatingCont);
а не stage.addChild(_floatingCont);
Значит _floatingCont добавляется в объект Main, а не на сцену. То же самое касается и всех других контейнеров. На сцену объект попадет только при явном указании на это, как в

stage.addChild(_floatingCont);


п.с. Советую почитать что такое инкапсуляция и зачем она нужна

nelco
20.09.2015, 15:11
Не надо путать stage и документ класс - это уловил, спасибо, важно!

если я не могу удалять из класса объект, который находится в Main или в Stage, то как мне тогда менять содержимое на stage или в Main? диспатчить события в Main и там ставить слушатели и выполнять нужные действия? нельзя как-нибудь "расшарить" объекты в Main, для другого класса? :)

caseyryan
20.09.2015, 15:20
диспатчить события в Main и там ставить слушатели и выполнять нужные действия?
Да.
нельзя как-нибудь "расшарить" объекты в Main, для другого класса?
Можно, но это будет неправильный подход. Нарушение инкапсуляции. Не нужно учиться сразу плохому. Это потом приведет к очень большим проблемам в архитектуре. Ладно какое-нибудь маленькое приложение, где легко все отследить и поправить. А если большое?
Говорю по опыту, лучше слать события) И вообще, тут уже много раз поднимались темы MVC, да и вообще нагуглить это очень просто. Так вот - это очень важная штука. Ее тоже нужно по возможности изучить как можно быстрее

Wolsh
20.09.2015, 16:47
Ну, MVC не MVC, но без хотя бы общего понимания ООП в AS3 будет крайне неуютно — ночь темна и полна ужаса, потому что AS3 построен на концепции ООП и старается поддерживать ее всеми силами, даже костылями. И пока основные понятия ООП для Вас темный лес, будет совершенно непонятно, как и, главное, почему все устроено именно так. Но начинать с ООП не получится, увы. Сначала надо какую-то синтаксическую базу освоить.
В двух словах по этой ситуации: если объект А создал объект В, то ссылка на объект В известна только ему одному. Важно понять, что НЕТ никакого общего реестра всех объектов, в который можно обратиться из любого места к любому объекту. Чтобы другие объекты могли получить эту ссылку, соответствующая переменная в объекте А должна "быть расшареной", на языке программистов — иметь модификатор доступа public. Модификаторы доступа определяют область видимости переменной. А если еще точнее — свойства. Свойствами называются переменные, объявленные в теле класса (переменные могут также объявляться в теле функций, и тогда доступ к ним возможен только в теле функции — такие переменные называются локальными и свойствами "всего" экземпляра не являются). Если переменная объявлена в теле класса, она доступна как минимум во всем коде класса, то есть во всех его функциях (методах). Даже если Вы не укажете модификатор явно, он будет назначен автоматически (по-умолчанию internal — доступен всем членам пакета). Модификатор public делает свойство доступным всем [у кого есть ссылка на экземпляр], а модификатор private закрывает доступ к свойству для всех других объектов, делая свойство "внутренним" для самого экземпляра (опустим тонкости и подробности).
Итак, в данной ситуации Вам нужно объявить не private, а
public var floatingCont:FloatingCont = new FloatingCont();(обратите внимание, что _ перед публичной переменной не ставится)
и далее обращаться к ней, как к свойству(!) объекта-хозяина, то есть мейна, который для всех детей доступен по ссылке root:
if (root.floatingCont.parent == root) {
root.removeChild(root.floatingCont);
}//я здесь опускаю морализаторство; все сказанное товарищами выше безусловно верно, и делать ТАК нельзя. Я просто демонстрирую, как оно работает, на Вашем примере. В AS3 вообще понятия "оно работает" и "хороший код" совершенно не обязательно тождественны ;)

ZackMercury
20.09.2015, 18:11
Мне кажется, у автора до сих пор проблемы с пониманием концепции дисплей листа...
Wolsh, скиньте ему то, что вы когда-то скидывали, дерево дисплей листа, вроде, чтобы он наглядно увидел, как оно всё на самом деле устроено, и расскажите про матрицы, ColorTransform, как они влияют на контейнер, фильтры и другие свойства DO.

nelco
20.09.2015, 19:27
Мне кажется, у автора до сих пор проблемы с пониманием концепции дисплей листа...
как я понимаю: DisplayList состоит весь из DOC-ов, корень - это Stage (создаётся автоматически), внутри него все объекты-DOC или DO , самый первый идёт Main.as потом дальше все вложено друг в друга, может быть вложено в Main, а может напрямую в Stage, вопрос в том, куда правильно всё отправлять? в Main или в Stage? судя по тому, что обращаться к stage (хотя бы для stage.addChild) можно из любого класса, то правильнее направлять DOC-ы сразу в Stage?... не понимаю только почему нельзя менять (удалять) DOC-ы, находящиеся в Stage из других классов, ведь это было бы удобно: класс обращается к stage, смотрит, есть ли там DOC с нужным именем (опять же непонятно как обращаться к DOC-y как если только не по имени переменной) и редактирует его... но сейчас, как выяснилось, это не правильно и непонятно как вообще (удалять контейнеры, находящиеся в Stage вызовом stage.removeChild(_objectName) не работает)...
например мне нужно удалить DOC, находящийся в Stage, например в Stage у него имя _floatingCont, мне нужно в классе (из которого я хочу удалить _floatingCont, находящийся в Stage) писать dispatchEvent("deleteFloatingCont"), а в stage регистрировать слушатель, который будет принимать событие "deleteFloatingCont" и только тогда удалять этот _floatingCont? но опять же, мне нужно, например, проверять содержит ли Stage этот _floatingCont, и если содержит, то удалять прошлый экземпляр (removeChild) и потом создавать новый экземпляр _floatingCont... как тогда проверить из другого класса, содержит ли Stage объект _floatingCont, если у класса нет доступа к такой "проверке" :\\

Wolsh, прочитал Ваш ответ, буду пробовать так, как Вы написали, пока не пойму как делать правильно... :\\

Добавлено через 25 минут
СaseyRyan, что такое MVC не знаю, в книжке Мука про это ещё не было ничего, нагуглю обязательно... спасибо за ответы!

Wolsh
20.09.2015, 22:04
Эмм.. не помню, чтобы я что-то "скидывал".. вот здесь (http://flasher.ru/forum/showpost.php?p=1143168&postcount=9) есть схемка.
А здесь (http://flasher.ru/forum/showpost.php?p=1147511&postcount=13) подборка "почему stage.addChild() это Зло".

nelco
21.09.2015, 12:11
package testProject
{
import as3Tutorial.scr.FloatingCont;
import flash.display.Sprite;

public class Main extends Sprite
{
public var floatingCont:FloatingCont = new FloatingCont();
private var _someClass:SomeClass = new SomeClass();


public function Main()
{
addChild(floatingCont);
addChild(_someClass);
}

}

}



package testProject
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;

public class SomeClass extends Sprite
{
private var _someText:TextField = new TextField();

public function SomeClass()
{
_someText.text = "button";
_someText.textColor = 0x800000;
addChild(_someText);

_someText.addEventListener(MouseEvent.CLICK, onClickListener);
}

private function onClickListener(e:MouseEvent):void
{
trace (root) // выводит [object Main]
trace (root.floatingCont); // Access of possibly undefined property floatingCont through a reference with static type flash.display:DisplayObject

}

}

}


всё равно нет доступа к floatingCont, созданному с атрибутом public

Модификатор public делает свойство доступным всем [у кого есть ссылка на экземпляр]
у меня в классе SomeClass нет же ссылки на экземпляр?

neonoviiwolf
21.09.2015, 12:36
как один из вариантов передачи ссылки


package testProject
{
import as3Tutorial.scr.FloatingCont;
import flash.display.Sprite;

public class Main extends Sprite
{
public var floatingCont:FloatingCont;
private var _someClass:SomeClass;


public function Main()
{
floatingCont= new FloatingCont();
_someClass= new SomeClass(floatingCont);
addChild(floatingCont);
addChild(_someClass);
}

}

}



package testProject
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;

public class SomeClass extends Sprite
{
private var _someText:TextField = new TextField();
public var floatingCont:FloatingCont;
public function SomeClass(_floatingCont:FloatingCont )
{
floatingCont = _floatingCont
_someText.text = "button";
_someText.textColor = 0x800000;
addChild(_someText);

_someText.addEventListener(MouseEvent.CLICK, onClickListener);
}

private function onClickListener(e:MouseEvent):void
{
trace (root) // выводит [object Main]
trace (root.floatingCont); // Access of possibly undefined property floatingCont through a reference with static type flash.display:DisplayObject

}

}

}



Добавлено через 2 минуты
можно ещё set/get, можно через наследование и т.д.

Добавлено через 3 минуты
хотя стоит ещё добавить слушателя сцены, а то мож ошибки посыпать

Добавлено через 5 минут
код нге проверял, мож чё не так, но смысл надеюсь понятен

Isfet
21.09.2015, 13:21
private function onClickListener(e:MouseEvent):void
{
trace (root) // выводит [object Main]
trace ((root as Main ).floatingCont); // Access of possibly undefined property floatingCont through a reference with static type flash.display:DisplayObject

}

Wolsh
21.09.2015, 14:55
А, ну да, надо же тип уточнить, чтобы свойство использовать.
Дело в том что свойство .root имеет тип DisplayObject, а в нем нет свойства .floatingCont
Поэтому надо уточнить, что root не просто DO, а его наследник Main.