[flash AS3] variabele variabelen ?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 09-09 18:55

murphsy

Product Monkey

Topicstarter
Een tijdje geleden deed ik mijn eerste echte stappen in flash cs4/as3 programmeerland. Inmiddels ben ik een stukje meer ervaren.

Een probleem waar ik echter al een aantal keren bij verschillende projecten tegenaan ben gelopen en waarvoor ik nog nooit een echt goede oplossing heb gevonden zijn variabele variabelen.
Variabele variabelen
Wat ik bedoel met variabele variabelen is het volgende:
Op basis van door de gebruiker ingevoerde data moeten en een aantal variabelen aangemaakt worden elk met een unieke naam. Aan elk van deze variabelen moet de gebruiker vervolgens een waarde kunnen toekennen.
Concretisering
Ik maak een tooltje waarmee zonder enige html kennis toch uitgebreide html-tabellen gemaakt kunnen worden. De gebruiker selecteert breedte (kolommen) en hoogte (rijen). Per kolom moet en een tableheader komen.

Met een for-loop wil ik deze tableheaders aanmaken. Stel de gebruiken voert voor de breedte '5' in:
for (p = 1; p <= 5; p++)
{
var header[nummer]:TextField = new TextField();
addChild(header[nummer]);
}

De headers zouden dus header1, header2, header3, header4 en header5 moeten heten. Het lukt me echter niet om een variabele te gebruiken in het aanmaken van een variabele. Googlen brengt me of té uitgebreide theorie of errors.

Wat zie ik over het hoofd? Alvast bedankt voor ieders tijd.

Acties:
  • 0 Henk 'm!

  • NetForce1
  • Registratie: November 2001
  • Laatst online: 18:26

NetForce1

(inspiratie == 0) -> true

Waarschijnlijk ben je op zoek naar arrays of dictionaries

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 09-09 18:55

murphsy

Product Monkey

Topicstarter
De dictionary class begreep/begrijp ik niet helemaal. In een array kan ik wel meerdere waarden opslaan maar niet in de vorm waarin ik wil. Ik wil met een loop X variabelen aanmaken, in elk van deze variabelen kan de gebruiker zelf een waarde opslaan. Even ter illustratie: X = 4

Dan maakt de loop dus:

variabeleX1, variabeleX2, variabeleX3, variabeleX4

De gebruiker kan vervolgens door middel van dynamische tekstinput waardes toevoegen, bijvoorbeeld:

variabeleX1 = aardbei
variabeleX2 = 125,85
variabeleX3 = horlogebandjesfabriek
variabeleX4 = pietpiraat

Door middel van een array zou ik de array [variabelen] kunnen maken met bijvoorbeeld:

array variabelen = aardbei // 125,85 // horlogebandjesfabriek // pietpiraat

Maar ik wil juist losstaande variabelen omdat er nog een stap tussen de loop en het toekennen van waardes zit. De loop telt hoeveel variabelen er nodig zijn en maakt voor elk een tekstvak en een variabele aan.

Dikgedrukt is eigenlijk wat ik wil.

Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Je moet omschakelen van denkwijze, want variabele variabelen zijn geen oplossing. Als je x tekstvakken en variabelen wilt hebben, dan maak je een array aan van grootte x. Daarin sla je op wat je maar wilt.

Vervolgens maak je ergens anders een nieuwe loop die over alle elementen in de array loopt en je maakt tekstvakken aan.

Tussen het vullen van de array en het maken van de tekstvakken kun je met de waarden in de array doen wat je wilt. In plaats van dat je variabeleX1 hebt (wat fout is), gebruik je gewoon variabeleX[1].

Let op dat een array bij 0 begint.

Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 09-09 18:55

murphsy

Product Monkey

Topicstarter
Goed uitgelegd, bedankt!

Echter; Arrays zijn lastig :)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
function maak_header()
    {
        
    for (var p = 1; p <= breedte; p++)
        {
            tabel_header.push(p);            
        }
        
    for (var q = 0; q <= breedte-1; q++)
                {  
                trace("tabelheader waarde: " +tabel_header[q]);  
                } 
    }


Bij invoer van 4 heb ik nu een array: tabel_header("1", "2", "3", "4").

Ik wil dat er nu tekstinput mogelijk is om bijvoorbeeld 1, 2, 3, 4 te veranderen in miep, noot, aap, mies. Ofwel 4 tekstvelden op de stage die elk één van de 'posities' in de array kunnen veranderen.

let op: het is belangrijk dat de tekstvelden aan een specifieke plek in de array gekoppeld zijn nadat ze zijn aangemaakt, zodat de gebruiker later nog kan wijzigen maar dat de volgorde gelijk blijft.

Ik denk aan iets als
code:
1
2
3
4
for (var q = 0; q <= tabel_header.length; q++)
    {
        maak voor elke waarde in de array een tekstinput aan die die waarde kan wijzigen
    }


Maar hier loop ik dus vast, hoe zeg ik: maak voor elke waarde in de array een tekstinput aan die die waarde kan wijzigen. Het probleem dat ik hierbij tegenkom is dat ik niet meerdere instances kan toevoegen met dezelfde naam.

In dit geval zouden er dus 4 tekstinput velden aangemaakt moeten worden die respectievelijk gekoppeld zijn aan tabel_header[1], tabel_header[2], tabel_header[3] en tabel_header[4]

Ik mis vast iets :)

Acties:
  • 0 Henk 'm!

Verwijderd

Daarom heb je ook dictionaries en objects. Dit zijn samen met arrays manieren om gestructureerd data bij te houden en aan mekaar te linken. "Variabele" variabelen vervuilen je namespace en zijn veel lastiger om mee te werken.

Bijvoorbeeld: (Ik gebruik java syntax highlighting maar het is gewoon AS3)
Java:
1
2
3
4
5
6
var dict:Dictionary = new Dictionary();
var field:TextField;
for(var i:int = 0; i < 4; i++){
  field = new Textfield();
  dict[field] = i;
}


En dan kan je gewoon zeggen:
Java:
1
dict[fieldref] = "miep";

Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 09-09 18:55

murphsy

Product Monkey

Topicstarter
In jouw voorbeeld maak ik 4 tekstvelden aan met de naam 'field'. Elk van deze tekstvelden kan ik waarden toewijzen, bijvoorbeeld (geen echte code maar soort van shorthand):
code:
1
2
3
4
5
6
7
8
9
10
11
for(var i:int = 0; i < 4; i++)
  { 
  field = new Textfield();
  dict[field] = i;
  }

dict[1] = "miep";
dict[2] = "aap";
dict[3] = "noot";

trace(dict[1]); geeft dan als output: miep


Maar dat is niet precies wat ik wil. Ik wil wel 4 tekstvelden aanmaken, maar van het type Input. Ik zou dan zou dictionary kunnen gebruiken maar ik snap niet hoe ik zou kunnen verwijzen naar de TextInput velden, aangezien ze allemaal dezelfde naam hebben. Bijv.:

code:
1
2
3
4
5
6
for(var i:int = 0; i < 4; i++)
  { 
  var tekstinputveld = new Textfield();
  tekstinputveld.type = TextFieldType.INPUT;
  dict[tekstinputveld] = i;
  }


Nu zou ik 4 tekstinputvelden hebben genummerd dict[1], dict[2], dict[3] en dict[4]. Uitstekend.

De gebruiker vult in de velden de waarden: piet, paul, klaas en jan in.

De volgende stap zou dan zijn de mannen namen in de velden opslaan in de dictionary. Dict[1] zou de waarde "piet" moeten bevatten en dict[4] de waarde "jan".

code:
1
dict[1] = tekstinputveld.text;


Maar hoe verwijs ik nou dict[1] naar het juiste tekstinput veld? Ze heten alle vier tekstinput :)

Acties:
  • 0 Henk 'm!

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 22:11
murphsy schreef op maandag 09 augustus 2010 @ 15:28:
Java:
1
2
3
4
5
6
7
8
9
10
11
for(var i:int = 0; i < 4; i++)
  { 
  field = new Textfield();
  dict[field] = i;
  }

dict[1] = "miep"; 
dict[2] = "aap";
dict[3] = "noot";

trace(dict[1]); geeft dan als output: miep

Maar hoe verwijs ik nou dict\[1] naar het juiste tekstinput veld? Ze heten alle vier tekstinput :)
Kan zijn dat het niet helemaal klopt. Mijn AS3 is wat roestig maar onderstaande zou ongeveer de strekking moeten zijn,
In je eerste voorbeeld vervang je de tekstvelden door een string en trace je vervolgens die string. Wat je eigenlijk had moeten doen was de text property van het tekstveld in de array moeten aanpassen.
Java:
1
2
3
4
5
6
7
8
9
10
11
12
for(var i:int = 0; i < 4; i++)
  { 
  field = new Textfield();
  dict[i] = field;
  }

dict[1].text = "miep"; //mogelijk dat je nog wat zal moeten casten naar een input veld
dict[2].text = "aap";
dict[3].text = "noot";

trace(dict[1]); geeft dan als output: een textveld met een leuke id.
trace(dict[1].text); geeft dan als output: miep

Het vervangen van een tekstveld in een array door een string kan je dan weer oplossen door gebruik te maken van een Vector

[ Voor 11% gewijzigd door Caelorum op 09-08-2010 16:30 . Reden: typos ^^ ]


Acties:
  • 0 Henk 'm!

  • NetForce1
  • Registratie: November 2001
  • Laatst online: 18:26

NetForce1

(inspiratie == 0) -> true

Waarom zou je nog de waardes in een aparte array opslaan? Maak gewoon een array van textfields, en refereer daar meteen aan.
Flash ActionScript:
1
2
3
4
5
6
7
8
9
10
for (var i:int = 0; i < 4; i++) {
    var field = new Textfield();
    fields[i] = field;
    // voeg evt. field toe aan gui
}
// uitlezen van textfields:
for (var i:int = 0; i < 4; i++) {
    var fieldValue = fields[i].text;
    // doe iets leuks met fieldValue
}


edit:
Caelorum schreef op maandag 09 augustus 2010 @ 15:43:
Java:
1
2
3
4
5
for(var i:int = 0; i < 4; i++)
  { 
  field = new Textfield();
  dict[field] = i;
  }
Dit klopt natuurlijk niet, je moet i als index gebruiken, en dan field opslaan, zo dus: dict[i] = field.

[ Voor 29% gewijzigd door NetForce1 op 09-08-2010 15:54 ]

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


Acties:
  • 0 Henk 'm!

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 22:11
NetForce1 schreef op maandag 09 augustus 2010 @ 15:52:
Dit klopt natuurlijk niet, je moet i als index gebruiken, en dan field opslaan, zo dus: dict[i] = field.
Zo goed had ik zijn ding nou ook weer niet doorgelezen maar bedankt voor het verbeteren..

Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 09-09 18:55

murphsy

Product Monkey

Topicstarter
Hmm. Voor vandaag is bij mij ook

if (inspiratie == 0) -> true {
stop();
}

Morgen ga ik aan de slag met je uitgebreide reactie. In elk geval Caelorum, NetForce1, Huhu en Egootje bedankt.

Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 09-09 18:55

murphsy

Product Monkey

Topicstarter
Jongens, jongens, jongens. Als jullie eens wisten wat een hersenkraker dit is voor mij. Volgens mij zouden jullie je zot lachen ;)

In elk geval heb ik de afgelopen twee dagen me verdiept in dictionary's en snap ik nu wat ze zijn, waarvoor ze dienen en hoe ik ze kan gebruiken. Ik weet zelfs wat het geboortedag-principe in de kansberekening is (ik ben misschien licht afgedwaald af en toe ;)).

Ik begrijp dat ik door middel van een dictionary objecten en waarden aan elkaar kan koppelen.

code:
1
2
3
4
5
for(var i:int = 0; i < 4; i++) 
  {  
  field = new Textfield(); 
  dict[i] = field; 
  }


hmm - reageer nog maar even niet - heb nog een ingeving - ik edit deze post wel zodra ik weer vast zit!

::edit::

Okay, ik heb een plaatje gemaakt die hopelijk uitlegt waar ik tegenaan loop :)
Afbeeldingslocatie: http://www.abonnementkeuze.com/images/tooltje.jpg

Ik wil dus een hash table (jaja, ik leer vaktermen hier ;)) waarin ik dus terug kan vinden dat in het eerste tekstveld 'aap' is ingevuld, in de tweede 'noot' etc.

Ik snap dat ik dit door middel van een dictionary kan doen, maar hetgeen waar ik tegenaan loop is dat alle 4 de tekstvelden dezelfde naam hebben (ze worden immers gecreëerd door één loop) - alle tutorials die ik kan vinden gaan uit van verschillende instance namen die ze vervolgens als sleutel gebruiken. De naam als sleutel gebruiken in onmogelijk aangezien ze hetzelfde heten...

[ Voor 33% gewijzigd door murphsy op 13-08-2010 14:41 ]


Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
Ik zie het probleem echt niet. Kwestie van je TextField instanties in een array stoppen en over het array itereren, toch? Snap je dit soort concepten niet, dan moet je toch echt eens gaan denken aan een basis cursus programmeer technieken. Zou je veel goed doen.

Acties:
  • 0 Henk 'm!

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 22:11
De textboxes kunnen niet dezelfde instancenamen hebben. Dat je telkens dezelfde variabelenaam gebruikt staat helemaal lost van welke instancenaam ze krijgen toegewezen.
Zoals hierboven al wordt gezegd zal je gewoon de textboxes aan een array/vector moeten toevoegen en een for-loop gebruiken om de waarden er weer uit te halen.

Ik denk dat je het beste eerst even hoofdstuk 3,4,5 en 8 kunt doornemen van dit boek (pdf) voordat je verder gaat.

Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 09-09 18:55

murphsy

Product Monkey

Topicstarter
R4gnax, een cursus zou waarschijnlijk geen kwaad kunnen nee :) Maar ik doe dit voor de hobby, gewoon in de avonduurtjes. Ik ben wat trager met het oppakken omdat ik totaal geen solide basis heb, maar beetje bij beetje leer ik steeds meer.

Caelorum, ik ga van 't weekend die hoofdstukken lezen. Bedankt voor de tip.

Goed nieuws alom: volgens mij heb ik het aan de praat :)

Acties:
  • 0 Henk 'm!

  • Alfredo
  • Registratie: Maart 2007
  • Laatst online: 31-07 19:40
Dictonaries gebruiken maar dan wel dict[1].text oproepen is uiteraard onzin. Dan gebruik je beter een array of vector.

Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
Alfredo schreef op maandag 16 augustus 2010 @ 19:48:
Dictonaries gebruiken maar dan wel dict\[1].text oproepen is uiteraard onzin. Dan gebruik je beter een array of vector.
Laat Vector maar links liggen, alles wat niet een Number, int of uint is komt toch onder de vergaarbak 'Object' terecht en wordt onder de kap nog steeds als vanouds afgehandeld. Java-style runtime-cast 'generics', dus. Wordt eens tijd dat Adobe wakker wordt en echte generics / templating aan ActionScript toevoegt, want het is zo zoetjes aan wel heel verleidelijk aan het worden om naar bijv. HaXe over te springen.

Acties:
  • 0 Henk 'm!

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 22:11
R4gnax schreef op dinsdag 17 augustus 2010 @ 08:43:
[...]


Laat Vector maar links liggen, alles wat niet een Number, int of uint is komt toch onder de vergaarbak 'Object' terecht en wordt onder de kap nog steeds als vanouds afgehandeld. Java-style runtime-cast 'generics', dus. Wordt eens tijd dat Adobe wakker wordt en echte generics / templating aan ActionScript toevoegt, want het is zo zoetjes aan wel heel verleidelijk aan het worden om naar bijv. HaXe over te springen.
Bedoel je daarmee dat je alleen Numbers mag gebruiken en dat je vervolgens zelf classes moet gaan maken gebasseerd op Object?
Lijkt me namelijk niet handig om een nieuwe implementatie van de al bestaande array en vector classes te maken :S

Acties:
  • 0 Henk 'm!

  • Alfredo
  • Registratie: Maart 2007
  • Laatst online: 31-07 19:40
Ik vermoed dat hij bedoelt dat de performancewinst die je kan behalen bij Vectors enkel opgaat voor Number, int en uint. Je kan elk datatype gebruiken voor een Vector.

R4gnax, dat vind ik overigens best wel vreemd. In AS3 is alles toch een Object? Of krijg je andere resultaten omdat Number, int en uint immutable objects zijn?

Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
Hoewel Vector.<T> pretendeert een generic / templated class te zijn, is deze dat eigenlijk helemaal niet. Onder de kap zijn er gewoon drie specialisaties gebouwd voor invulling van type parameter T, te weten: Number, int en uint. Past de invulling van T niet in één van die drie, dan wordt een catch-all gebruikt die klaarblijkelijk intern met Object werkt.

Als je een C++ achtergrond hebt dan herken je dat wellicht als een vorm van partial template specialization. Alleen wel een heel vreemde, aangezien het concept van templates of generics eigenlijk niet bestaat. Vector leunt dan ook op hacks die door Adobe in hun compiler(s) aangebracht zijn, zodat ze met relatief weinig effort toch het meest voorkomende usage scenario van generics / templates, namelijk: typed collections, konden ondersteunen.

Voor de drie specialisaties is de performance winst het wel waard voor het itereren over collecties (tot 60% sneller o.i.d.), maar splice, slice, etc. operaties schijnen dan weer veel duurder te zijn dan op de Array class. Afhankelijk van andere componenten waar je mee samen werkt zul je wellicht ook vaak naar een Array moeten converteren. Dat geldt ook voor de basis Flash bibliotheek en het Flex framework, aangezien Vector de enige 'niet-echt-generic' is. Daarnaast is het typed parameter mechanisme, omdat het een compiler hack is, uiteraard niet te gebruiken voor eigen classes (en is Vector.<T> gemarkeerd als final). Dat tezamen maakt Vector.<T> dus echt een derde wiel.

Acties:
  • 0 Henk 'm!

Verwijderd

In het loopje waar je de TextFields aanmaakt dien je ze niet alleen als child aan de stage toe te voegen, zoals je nu al doet, maar tevens toe te voegen aan een array.
Initieer de nieuwe array vóór het loopje:

code:
1
var mijnVelden:Array = new Array();


En voeg de tekstvelden nu toe aan deze array, in je loopje:

code:
1
2
3
// ...
addChild(headerinput_txt);
mijnVelden.push(headerinput_txt);


Als er nu op de button "opslaan" wordt gedrukt, kun je door de array "mijnVelden" itereren en de waarden uitlezen:

code:
1
2
3
for(var i=0; i < mijnVelden.length; i++) {
trace(mijnVelden[i].text);
}


:)
Pagina: 1