2010-04-14 8 views
0

Voici l'affaire: je travaille sur un portefeuille personnel en AS3 et j'ai rencontré un problème auquel je n'arrive pas à trouver une réponse logique. Je veux que tout (enfin, la plupart) soit éditable avec un fichier XML, y compris mon menu. Mon menu est juste un Sprite avec du texte dessus et un Tween-tween, pas de problème. Mais, j'ai oublié de penser à un moyen de déterminer quel élément de menu j'ai cliqué.Comment savoir quel objet j'ai cliqué?

C'est dans mes Main.as

private function xmlLoaded(e:Event):void { 
    xml = e.target.xml; 
    menu = new Menu(xml); 
    menu.x = 0; 
    menu.y = stage.stageHeight/2 - menu.height/2; 
    addChild(menu); 
} 

Dans Menu.as

public function Menu(xml:XML) { 
    for each (var eachMenuItem:XML in xml.menu.item) { 
     menuItem = new MenuItem(eachMenuItem); 
     menuItem.y += yPos; 
     addChild(menuItem); 
     yPos += menuItem.height + 3; 
    } 
} 

et dans mes MenuItem.as, tout fonctionne - je une interpolation de fantaisie quand je passe la souris dessus, mais quand je clique sur un élément de menu, je veux que quelque chose apparaisse du cours. Comment savoir sur lequel j'ai cliqué? J'ai essayé de tout pousser dans un tableau, mais cela n'a pas bien fonctionné (ou peut-être que je me trompe). J'ai également essayé un compteur global, mais cela ne fonctionne pas non plus car la valeur sera toujours la quantité d'éléments dans mon fichier XML. Également essayé e.currentTarget dans ma fonction de clic, mais quand je trace cela, tous sont "Object Sprite" .. J'ai besoin de quelque chose pour que je puisse donner à chacun un "nom" unique?

Merci d'avance!

Répondre

2

Vous pouvez simplement définir une variable de nom dans la classe MenuItem et l'utiliser. Par ailleurs, dans le gestionnaire d'événements, vous pouvez utiliser (e.currentTarget as MenuItem).name (ou tout simplement e.currentTarget.name)

Par ailleurs, vous savez que pour chaque .. ne garantit pas de traverser le xml dans le bon ordre?

+1

Lorsque j'utilise la propriété name (si c'est ce que vous voulez dire), j'obtiens "instance4", "instance9", "instance14" dans ma trace dans le gestionnaire Click. Même quand je mets menuItem.name = "item" + compteur; dans mon Menu.as, je reçois toujours instanceX. Quand j'ai essayé de le lancer sur MenuItem (avec comme MenuItem), j'ai "null" (comme jolyonruss expliqué ci-dessous). Quand j'utilise un casting dur, je reçois # 1034: Impossible de convertir Sprite en MenuItem ... (Dois-je travailler avec un compteur?Je suis complètement perdu ici) Merci pour votre réponse! – Nick

+0

patientez ... à quoi attachez-vous exactement l'écouteur d'événement? jolyonruss et moi avions supposé que vous étiez en train de l'attacher au menu, mais évidemment ce n'est pas le cas. La définition du nom fonctionnera, mais e.currentTarget pointe vers la mauvaise chose et ne trouve donc pas la variable de nom mise à jour. Si vous nous dites à quoi correspond l'écouteur d'événement, nous pouvons peut-être vous aider. Vous n'aurez probablement pas besoin d'utiliser un dictionnaire. – jonathanasdf

+0

Dans mon MenuItem.as, je fais une "barre" (un Sprite avec un fond noir), j'ajoute le texte de mon XML dessus (dans mon Menu.as il fait une nouvelle instance de cette barre, et laisse une marge de 3px). Donc, dans mon MenuItem.as, j'ai un couple d'eventListeners. L'un d'entre eux est bar.addEventListener (MouseEvent.CLICK, mouseClickHandler). D'autres sont MOUSE_OVER/MOUSE_OUT pour faire cette interpolation de fantaisie dont je parlais. Cela fonctionne (sur chacun des 3 objets que j'ai maintenant), mais le CLIC me fait arracher tous mes cheveux. Merci pour votre réponse déjà, Jonathan :) – Nick

0

J'ai une réponse similaire, mais j'utiliserais un objet Menu Cast dur (e.currentTarget) au lieu d'un casting doux en utilisant le mot-clé comme. La raison en est que si vous avez accidentellement casté au mauvais type, un soft cast ne retournera que null, alors qu'un cast hard vous donnera une erreur d'exécution correcte et un numéro de ligne dans votre code où le problème est.

Je voudrais aussi vous suggérons d'ajouter une fonction publique à MENUITEM pour obtenir une référence ou un index unique de sorte que vous pouvez faire quelque chose comme ça dans le gestionnaire d'événements Click MenuItem

private function onMenuItemClick(event : MouseEvent) : void{ 

    // this could be a int, ie. the node index in the XML 
    var uniqueSectionReference : String = MenuItem(event.currentTarget).uniqueReference; 

    dispatchEvent(new MenuEvent(MenuEvent.CHANGE, false, false, uniqueSectionReference)); 

    // or if you have a reference in Menu for whatever it is thats controlling your content you could do this 

    contentHolder.showSection(uniqueSectionReference); 

} 
0

Vous pouvez également regarder dans le dictionnaire classe - Je me retrouve à l'utiliser de plus en plus pour ce genre de choses. Fondamentalement, il agit comme un tableau, mais au lieu d'associer vos valeurs aux clés d'index, il vous permet de mapper des références d'objet à d'autres références d'objet. Ainsi, par exemple, vous pouvez mettre en place quelque chose comme ceci:

// create your buttons 
var button1:MyButton = new MyButton(); 
var button2:MyButton = new MyButton(); 
var button3:MyButton = new MyButton(); 

// declare and instantiate a dictionary object 
var links:Dictionary = new Dictionary(); 

// populate your dictionary object, mapping values to your buttons. 
links[button1] = "http://www.button1URL.com"; 
links[button2] = "http://www.button2URL.com"; 
links[button3] = "http://www.button3URL.com"; 

// group buttons into an array for convenience 
var buttons:Array = [button1, button2, button3]; 

// add event listener to your button 
for each (var b:MyButton in buttons) { 
    b.addEventListener(MouseEvent.CLICK, clickHandler); 
} 

// handle the button click by getting the relevant information for the clicked button from 
// your dictionary object 
function clickHandler(e:MouseEvent):void { 
    navigateToUrl(new URLRequest(links[e.currentTarget])); 
} 

Votre exemple est évidemment un peu plus complexe - vous aurez besoin d'inclure la valeur de votre URL ou tout autre dans votre XML et ensuite traiter de cette façon. Selon ce que vous faites, vous n'aurez peut-être pas besoin du dictionnaire - e.currentTarget.MyValue peut très bien fonctionner si les données sont incluses dans le bouton lui-même.

Espérons que ça aide!

+0

Merci pour votre réponse étendue, Myk. J'ai fait quelques recherches sur la classe Dictionary, mais je n'arrive pas à la comprendre complètement (probablement parce que ma situation est un peu plus complexe, oui). J'ai essayé dict [menuItem] = "item" + compteur; dans mon Menu.as, quand je trace cela (dans Menu.as), j'obtiens item1-2-3 donc c'est génial. De retour dans mon MenuItem.as, le e.currentTarget de Clickhandler est un Sprite. Alors, comment puis-je laisser le dictionnaire et le Sprite cliqué "communiquer" les uns avec les autres? Je voudrais avoir quelque chose comme si (e.currentTarget == Menu.dict ["item1"]) ... Toute aide serait appréciée. Merci! – Nick

+0

Je suis content que vous l'ayez réglé ci-dessus. Le dictionnaire n'est peut-être pas tout à fait ce dont vous avez besoin ici - je pense que le point que j'essayais de faire est que même sans un nom unique chaque occurrence que vous créez est toujours reconnue par Flash comme un objet unique. Le dictionnaire tend à rendre ce fait évident, puisque vous n'avez rien à nommer - vous pouvez lier une référence abstraite à une autre, un point d'index de tableau à un autre et ne rien savoir sur les détails de ces instances. Plutôt que si (e.currentTarget.name == x) alors y, écrivez le code qui fait (e.currentTarget.y) et vous êtes défini. Cela a-t-il du sens? – Myk

Questions connexes