PDA

Просмотр полной версии : Обратится к тестовому полю


donphp
24.11.2009, 01:29
Есть текстовое поле с Instance name did_field

В AS2 обращался
_root.did_field.text = 0;

Как изменить текст внутри него в AS3
Так не работает

import flash.display.DisplayObject;
import flash.display.Sprite;
root.did_field.text = 0;



1119: Обращение возможного неопределенного свойства did_field через ссылку со статическим типом flash.display:DisplayObject .

TanaTiX
24.11.2009, 02:08
getChildByName("name")

SamFR
24.11.2009, 02:13
Не работает, потому что в классе MovieClip не определено свойство did_field, о чём вам и говорит компилятор.

Как быть? Отключить автоматическое объявление stage instances. Написать Document Class, в котором определить публичную переменную с тем же именем, что вы задали полю (пусть будет txt). Обращаться (root as ИмяВашегоDocumentClass).txt.text = 'текст'.

Сразу оговорюсь, это не лучший вариант. Во-первых, чуть лучше будет определить в Document Class метод, изменяющий содержимое поля. А, во-вторых, ещё лучше будет уйти от привязки к root, т.к. в рельных проектах она только мешает (да и в тестовых тоже не советовал бы её использовать).

Добавлено через 54 секунды
getChildByName("name")

Тоже можно, но это ещё хуже :)

kaetano
24.11.2009, 02:23
ИМХО (я спец еще тот):

Если Вы все пишете в кадрах, то я думаю root вообще не нужен.
Подключите библитеку: import flash.text.*; Хотя.... если из кадра пишете, то вроде вообще не надо ничего подключать - просто:
did_field.text = String(0);
0 нельзя присвоить текстовому полю, нужно преобразование к строке: =String(0);

А лучше заведите основной класс (подключать его умеете?) имеется в виду что текстовое поле уже существует на основной сцене:

import flash.display.Sprite;
import flash.text.*;

public class Main extends Sprite{
public var did_field:TextField;
public function Main(){
did_field.text = String(0);
}
}

SamFR
24.11.2009, 02:29
А лучше заведите основной класс :

import flash.display.Sprite;
import flash.text.*;

public class Main extends Sprite{
public var did_field:TextField;
public function Main(){
did_field.text = String(0);
}
}


Об этом я и говорил, но всё же лучше хотя бы метод-сеттер сделать:


import flash.display.Sprite;
import flash.text.TextField;

public class Main extends Sprite{
private var did_field:TextField;

//...

public function set fieldText(value:String):void{
did_field.text = value;
}
}

kaetano
24.11.2009, 02:37
Об этом я и говорил, но всё же лучше хотя бы метод-сеттер сделать:


import flash.display.Sprite;
import flash.text.TextField;

public class Main extends Sprite{
private var did_field:TextField;

//...

public function set fieldText(value:String):void{
did_field.text = value;
}
}


Что-то у меня сомнения насчет сеттера. Он же должен присваивать значение переменной, а не текстовому полю, да и еще объявленному как private. У Вас нет ошибки при компиляции?:quiet:

SamFR
24.11.2009, 03:33
А почему тут должна быть ошибка компиляции?)

Я, наверное, был неправ, не упомянув тот факт, что пример в своём предыдущем посте я привёл исходя из того, что текстовое поле будет создано динамически (в конструкторе, например). Если оставить поле на рабочем столе, то будет ошибка исполнения.

Что-то у меня сомнения насчет сеттера. Он же должен присваивать значение переменной, а не текстовому полю, да и еще объявленному как private.

Господи, кто вам такое сказал? O_o
Сеттер никому и ничего не должен, даже вам :D
Во-вторых, здесь значение присваивается не текстовому полю, а его свойству text. К тому же, чем вам did_field не переменная?) Ну, и в третьих, сеттер, как и геттер – по сути те же методы, и доступ к закрытым переменным своего класса имеют не менее, чем методы.

donphp
24.11.2009, 15:32
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.*;
import flash.net.*;
import flash.text.*;


Пробовал

root.getChildByName("did_field").text = String(0);


root.getChildByName("did_field").text = String(0);


Классы подключать не умею.
А если подключить класс то код в кадрах писать нельзя?
А как обращаться к классу из клиппа

SamFR
24.11.2009, 16:38
Код в кадрах писать можно, но нежелательно, если вы хотите делать что-нибудь более-менее серъёзное.

Классы подключать очень просто. Попробуйте:


package {
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
import flash.text.TextField;
import flash.display.MovieClip;

/**
* Основной класс документа (Document Class).
* Является потомком MovieClip. Это значит, что любой объект этого класса будет иметь
* те же свойства и методы, что и MovieClip, плюс те, которые определите вы. Также это
* значит, что с любым объектом этого класса можно обращаться, как с объектом MovieClip.
*/
public class MainClass extends MovieClip {

/**
* Закрытое свойство. Доступ к нему будет возможен только изнутри этого класса.
*/
private var did_field:TextField;

/**
* Конструктор класса. Вызывается при создании экземпляра класса (в нашем случае –
* при запуске флешки).
*/
public function MainClass() {
//создаём текстовое поле
did_field = new TextField();
did_field.defaultTextFormat = new TextFormat('_sans', 14);
did_field.selectable = false;
did_field.autoSize = TextFieldAutoSize.LEFT;
did_field.x = did_field.y = 20;

//добавляем его в контейнер (аналогично помещению на рабочую область в Flash IDE)
addChild(did_field);

//пользуемся методом-сеттером для установки текста поля.
fieldText = 'Текст поля did_field';
}

/**
* Метод-геттер. Позволяет получить текст поля.
* Ключевое слово public означает, что доступ к свойству fieldText для чтения
* можно будет получить извне.
*/
public function get fieldText():String{
return did_field.text;
}

/**
* Метод-геттер. Позволяет установить текст поля.
* Ключевое слово public означает, что доступ к свойству fieldText для записи
* можно будет получить извне.
*/
public function set fieldText(value:String):void {
did_field.text = value;
}

}
}


Этот текст задаёт Document Class – основной класс документа. Его нужно сохранить в файл "MainClass.as". Далее создайте в той же папке .fla - файл, и пропишите в поле "Class" имя основного класса – MainClass. После запуска флешки будет создано текстовое поле, и ему будет установлен текст.

К экземпляру класса обращаться можно, как к любой другой переменной (точнее, любая переменная во флеше на самом деле хранит ссылку на экземпляр какого-то класса, будь то String, MovieClip или TextField). Однако важно помнить, что для доступа к членам класса (свойствам и методам) переменная, хранящая ссылку на экземпляр, должна быть нужного типа.

Например, определим класс ColorRect:


package {
import flash.display.Sprite;

/**
* Закрашенный прямоугольник.
*/
public class ColorRect extends Sprite {

/**
* Конструктор.
*/
public function ColorRect() {
super();
}

/**
* Закрашивает заданным цветом прямоугольник 50x50.
*
* @param newColor:uint Цвет заполнения.
*/
public function fillBy(newColor:uint = 0xA2A2A2):void{
with(graphics){
clear();
lineStyle(0, newColor);
beginFill(newColor);
drawRect(0, 0, 50, 50);
endFill();
}
}

}
}


Данный класс имеет публичный метод fillRect(). Сохраним этот класс в файле ColorRect.as в той же папке, что и MainClass.as. Изменим MainClass.as следующим образом:


package {
import flash.display.MovieClip;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;

/**
* Основной класс документа (Document Class).
*/
public class MainClass extends MovieClip {

/**
* Закрытое свойство. Доступ к нему будет возможен только из этого класса.
*/
private var did_field:TextField;

/**
* Конструктор класса. Вызывается при создании экземпляра класса (в нашем случае –
* при запуске флешки).
*/
public function MainClass() {
//создаём текстовое поле
did_field = new TextField();
did_field.defaultTextFormat = new TextFormat('_sans', 14);
did_field.selectable = false;
did_field.autoSize = TextFieldAutoSize.LEFT;
did_field.x = did_field.y = 20;

//добавляем его в контейнер (аналогично помещению на рабочую область в Flash IDE)
addChild(did_field);

//пользуемся методом-сеттером для установки текста поля.
fieldText = 'Текст поля did_field';

var colorRect:ColorRect;
//var colorRect:Sprite;

//создаём экземпляр ColorRect
colorRect = new ColorRect();
colorRect.x = did_field.x - 5;
colorRect.y = did_field.y - 5;
colorRect.width = did_field.width + 10;
colorRect.height = did_field.height + 10;

//добавляем его в контейнер.
addChildAt(colorRect, 0);

//вызываем метод класса ColorRect.
colorRect.fillBy(0x9EACE0);
}

/**
* Метод-геттер. Позволяет получить текст поля.
*/
public function get fieldText():String{
return did_field.text;
}

/**
* Метод-геттер. Позволяет установить текст поля.
*/
public function set fieldText(value:String):void {
did_field.text = value;
}

}
}


В конструкторе мы объявляем переменную типа ColorRect и присваиваем ей новый экземпляр класса ColorRect. Далее задаём его положение и добавляем в контейнер, а затем вызываем публичный метод, определённый в классе ColorRect.

Если же мы теперь вместо var colorRect:ColorRect напишем var colorRect:Sprite, то возникнет ошибка в строчке colorRect.fillBy(0x7285D1). Почему именно там? До этого всё будет нормально, так как ColorRect является потомком Sprite, и мы можем присвоить его переменной типа Sprite. Также можно пользоваться свойствами x, y, width и height, которые класс Sprite унаследовал от DisplayObject. А вот метод fillBy() в классе Sprite не определён, мы ведь его определили только в ColorRect. Поэтому, если объявить переменную как Sprite, то этот метод вызвать не удастся, несмотря на то, что он публичный. Однако можно в этом случае привести тип переменной: (colorRect as ColorRect).fillBy(0x7285D1), и всё пройдёт удачно, так как переменная colorRect на самом деле хранит экземпляр класса ColorRect.

Именно поэтому у вас и возникала ошибка с текстовым полем. Флеш при компиляции создаст класс, являющийся наследником DisplayObject, в котором будет свойство did_field типа TextField, так как вы добавили текстовое поле с этим именем на сцену. Экземпляром этого класса и будет являться объект root. Но к объекту в памяти мы можем обратиться только через переменную. А переменная (свойство) DisplayObject.root имеет тип DisplayObject, в котором свойство did_field не определено. Отсюда ошибка.

donphp
24.11.2009, 18:12
Смотрю на все это дело и голова оху.......... :eek:
Гора кода для того что бы просто вывести текст на экран

Ладно сейчас поробуем

SamFR
24.11.2009, 18:38
Для того, чтобы вывести текст на экран, нужны только эти строчки:

did_field = new TextField();
did_field.defaultTextFormat = new TextFormat('_sans', 14);
did_field.selectable = false;
did_field.autoSize = TextFieldAutoSize.LEFT;
did_field.x = did_field.y = 20;
addChild(did_field);

И то обязательны из них только первая и последняя. Всё остальное – это пример обращения с классами и попытка объяснить некоторые моменты.
Конечная цель вашего приложения, смею надеятся, состоит же не в выводе строчки текста? Она, наверное, более масштабна, и включает в себя набор подзадач. Вот для решения этих составных задач и нужны классы. Эффективность использования ООП растёт пропорционально размеру проекта. Я бы даже сказал, не пропорционально, а в геометрической прогрессии)

donphp
24.11.2009, 19:02
Заработало. Кстати мой код тоже заработал
достаточно было убрать root

SamFR спасибо Вам конечно огромное.


Но хер с ними с теми классами. Пока думаю и без них можно
Я так понял моя проблема была в том что путь к тестовому полю был не правильный

Через root.did_field.text = '8888'; - не работало, а через this.did_field.text = '8888'; - заработало

Собственно вопросы.
1. Как будет выглядеть правильный абсолютный путь к объекту который на сновной сцене (то что я создам сразу после создания нового fla)
2. как получить доступ к переменным переданным через FlashVars из html

SamFR
24.11.2009, 20:38
Через root.did_field.text = '8888'; - не работало, а через this.did_field.text = '8888'; - заработало

Собственно вопросы.
1. Как будет выглядеть правильный абсолютный путь к объекту который на сновной сцене (то что я создам сразу после создания нового fla)
2. как получить доступ к переменным переданным через FlashVars из html

Если вы обращаетесь непосредственно из рута, то, конечно, заработает. Если же вы хотите обратиться к объекту, расположенному на основной сцене, извне (то есть из какого-то другого объекта), то вы этого просто так сделать не сможете, потому что свойство root имеет тип DisplayObject.

Если вы так уж сильно не хотите работать с классами, можете использовать конструкцию (root as Object).имяОбъекта. Тем самым вы приведёте статический тип DisplayObject к динамическому Object.


(root as Object).did_field.text = '8888';


Но лучше привыкайте к ООП, бе него сейчас никак :)
Переменные, полученные через FlashVars, можно получить в виде хэша DisplayObject.loaderInfo.parameters:


//выводит значение переменной myVar
trace(loaderInfo.parameters['myVar']);