AS3. EventListener.Click depends on position - actionscript-3

I'm doing a button on AS3 made out of a sprite wich (just a simple square). When I add the event listener so that it acts as a button it works but depending on button.x, so when I put the button where I want the button stops working.
Thanks
public function pintaInterficieTrad(){
while(numChildren != 0) removeChildAt(0);
var idioma = new TextField();
idioma.text=traductor.*[numTrad].*;
idioma.width=200;
idioma.selectable=false;
idioma.setTextFormat(format);
idioma.x=20;
idioma.y=20;
addChild(idioma);
var trad = new Sprite();
trad.graphics.lineStyle(5,0x00ff00);
trad.graphics.beginFill(0x000000);
trad.graphics.drawRect(300,20,150,70);
addChild(trad);
var textTrad = new TextField();
if(numTrad==0) {
textTrad.text="Traduir";
}else{
textTrad.text="Traducir";
}
textTrad.width=200;
textTrad.selectable=false;
textTrad.setTextFormat(format);
textTrad.x=270;
textTrad.y=40;
addChild(textTrad);
var getBack = new Sprite();
getBack.graphics.lineStyle(5,0x00ff00);
getBack.graphics.beginFill(0x000000);
getBack.graphics.drawRect(500,20,150,70);
addChild(getBack);
var textgetBack = new TextField();
if(numTrad==0) {
textgetBack.text="Tornar";
}else{
textgetBack.text="Volver";
}
textgetBack.width=200;
textgetBack.selectable=false;
textgetBack.setTextFormat(format);
textgetBack.x=470;
textgetBack.y=40;
addChild(textgetBack);
trad.addEventListener(MouseEvent.CLICK,traduirBtn);
getBack.addEventListener(MouseEvent.CLICK,tornarBtn);
var userBox = new Sprite();
userBox.graphics.lineStyle(2,0x00ff00);
userBox.graphics.beginFill(0xffffff);
userBox.graphics.drawRect(40,130,610,160);
addChild(userBox);
var tradBox = new Sprite();
tradBox.graphics.lineStyle(2,0x00ff00);
tradBox.graphics.beginFill(0xffffff);
tradBox.graphics.drawRect(40,320,610,160);
addChild(tradBox);
var formatTxt = new TextFormat();
formatTxt.color=0x000000;
formatTxt.size=14;
var textUser = new TextField();
var textTraduit = new TextField();
textUser.defaultTextFormat=formatTxt;
textUser.text = textUsuari;
textUser.width = 600;
textUser.height = 150;
textUser.x=45;
textUser.y=130;
addChild(textUser);
textTraduit.text = traduccio;
textTraduit.setTextFormat(formatTxt);
textTraduit.width = 600;
textTraduit.height = 150;
textTraduit.x=45;
textTraduit.y=325;
addChild(textTraduit);
}
public function traduirBtn(e){
while(numChildren != 0) removeChildAt(0);
tradueix();
pintaInterficieTrad();
}
public function tornarBtn(e){
while(numChildren != 0) removeChildAt(0);
pintaMenu();
}
}
If I put the squares on x=0 they do what they're suposed to do...

seems like the button you're talking about is trad. You're addChilding it quite early in your code, which means that antoher displayobject could get above it at the same position. When you click at that position, the click event will only get send to the top most element, so try adding the elements you want people to interact with as the last (buttons, text field inputs, etc.)

Your problem is in the fact that you are adding the text over the button and the text is being clicked, not the button.
Add the text to the button itself and your click event will work.
Also verify that no other component is covering the button. Even if transparent, like a textbox.

Related

Clearing content from a movieclip in a blank keyframe in AS3

var loader:URLLoader;
var allWords:Array;
var thisWord:String;
var textContainer:MovieClip;
var textFields:Array;
var textStyle:TextFormat;
var underline:MovieClip;
var numCorrect:uint;
var totalLetters:uint;
var misses:uint;
var missesToLose:uint;
function initializeGame():void
{
loader = new URLLoader();
allWords = new Array();
textContainer = new MovieClip();
textFields = new Array();
textStyle = new TextFormat();
textStyle.font = "Courier New";
textStyle.size = 48;
textStyle.bold = true;
Hi All,
I have created this game and only added the beginning portion of the code. The entire code would be tedious to go through. I want to click a button and go to a clear keyframe, however when I test the movie the underline movieclip still shows. How can I clear the frame completely, do I have to removeChild for the movieclip? How do I do that? Is there a way to completely unload the SWF for this game after it is loaded? If so what code can I use?
Thanks

event listener not being called

How can I resolve my problem?
I load all images and image buttons when I click on a button but after that when I try to click on close button (image4) the event listener cannot listen because everything is set in another function.
private function onShop(evt:MouseEvent)
{
shop.removeEventListener(MouseEvent.CLICK, onShop);
var container:Sprite = new Sprite();
var ibutton:Sprite = new Sprite();
addChild(container);
addChild(ibutton);
ibutton.buttonMode = true;
function loadImage(path:String):Loader
{
var request:URLRequest = new URLRequest(path);
var loader:Loader = new Loader();
loader.load(request);
return loader;
};
var image1 = loadImage("image/inventory/shop_windoww.png");
image1.x = 200;
image1.y = 40;
this.addChildAt(image1,8);
var image2 = loadImage("image/inventory/title_window.png");
image2.x = 200;
image2.y = 14;
container.addChild(image2);
var image3 = loadImage("image/inventory/icon_window.png");
image3.x = 177;
image3.y = 7;
container.addChild(image3);
var image4 = loadImage("image/inventory/close.png");
image4.x = 891;
image4.y = 39;
ibutton.addChild(image4);
var image5 = loadImage("image/inventory/button_ok.png");
image5.x = 450;
image5.y = 485;
ibutton.addChild(image5);
var image6 = loadImage("image/inventory/button_ok.png");
image6.x = 782;
image6.y = 485;
ibutton.addChild(image6);
image4.addEventListener(MouseEvent.CLICK, test);
}
private function test(evt:MouseEvent)
{
image4.removeEventListener(MouseEvent.CLICK, test);
trace("ca marche");
}
Declare your variables outside of the onShop scope. They seem to have more sense as global variables, not only local (because you are trying to use the same variables declared on the onShop method on test method).
I also recommend you some points:
Use an external file (JSON/XML) to get all image URLs, or just use a simple Array with hardcoded content;
Use a for loop to load all images (after following the previous suggestion);
Use event.currentTarget in your test method, so, you can deal with those images with a more generic way.
[event.currentTarget] The object that is actively processing the Event object with an event listener. For example, if a user clicks an OK button, the current target could be the node containing that button or one of its ancestors that has registered an event listener for that event.

Custom ContextMenu is not showing, since Display Object is lying "on Top"

as a follow up to another question here:
i've build a custom contextmenu item in a flash application and had a problem with it not showing sometimes.
i found out that the issue was that another sprite was lying "on top" of the item with the custom contextmenu.
however, even with the "mouseEnabled" and "mouseChildren" properties set to false for the item "on top" i still cannot get the custom contextmenu to show...
any ideas? thanks!
ps: here is some code to see the problem:
var spr:Sprite=new Sprite();
spr.graphics.beginFill(0xff0000,1);
spr.graphics.drawRect(0,0,100,100);
addChild(spr);
var blocker:Sprite=new Sprite();
blocker.x=50
blocker.y=50
blocker.graphics.beginFill(0x00ff00,1);
blocker.graphics.drawRect(0,0,100,100);
addChild(blocker);
blocker.mouseEnabled=false
blocker.mouseChildren=false
var customContextMenu:ContextMenu = new ContextMenu();
var item:ContextMenuItem = new ContextMenuItem("custom item");
customContextMenu.customItems.push(item);
item.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, menuItemSelectHandler,false,0,true);
spr.contextMenu = customContextMenu;
function menuItemSelectHandler(cem:ContextMenuEvent) {
trace("hello context");
};
when the mouse is over the green rect, the custom contextmenuitem is not shown
The context menu for an object will be displayed only if the user right-clicks directly on that object itself, as far as I know.
I've simplified your problem in this code:
public class Test extends Sprite
{
public function Test()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
var sprite:Sprite = new Sprite();
addChild(sprite);
sprite.graphics.beginFill(0xFF0000);
sprite.graphics.drawRect(0, 0, 200, 200);
sprite.graphics.endFill();
var shape:Shape = new Shape();
addChild(shape);
shape.graphics.beginFill(0x0000FF, .6);
shape.graphics.drawRect(100, 100, 200, 200);
shape.graphics.endFill();
setUpContextMenu(sprite);
}
private function setUpContextMenu(target:InteractiveObject):void
{
var menu:ContextMenu = new ContextMenu();
target.contextMenu = menu;
var item:ContextMenuItem = new ContextMenuItem("About Us");
menu.customItems.push(item);
}
}
When you right-click on the area where the red and blue squares overlap, you don't get the custom context menu.
Here's a possible solution, where I've modified only the setUpContextMenu() function:
private function setUpContextMenu(target:InteractiveObject):void
{
var menu:ContextMenu = new ContextMenu();
this.contextMenu = menu;
var item:ContextMenuItem = new ContextMenuItem("About Us");
var handler:Function = function (event:ContextMenuEvent):void {
// Start with empty menu.
var items:Array = [];
if (event.mouseTarget == target) {
// Directly right-clicked on target. Add custom item.
items = [item];
} else if (event.mouseTarget is DisplayObjectContainer) {
var o:DisplayObjectContainer
= DisplayObjectContainer(event.mouseTarget);
var pt:Point = o.localToGlobal(new Point(o.mouseX, o.mouseY));
var arr:Array = o.getObjectsUnderPoint(pt);
// One of the mouse target's descendants is our target,
// directly under the pointer. Add custom item.
if (arr.indexOf(target) != -1)
items = [item];
}
menu.customItems = items;
};
menu.addEventListener(ContextMenuEvent.MENU_SELECT, handler);
}
Here I'm assigning the context menu to the application itself. On the "menuSelect" event, I customize it based on whether the mouse pointer is somewhere above the red square.

as3 moving image from one mc to another

With the code below I created some imgMcA and some imgMcB then I loaded images into imgMcA ones. ImgMcBs have no image at that moment. So if one of imgMcA is clicked the image should be transferred to one of the empty imgMcBs (may be randomly) and if imgmcB is clicked later the image should move back to its imgMcA back. I could not find out how I can accomplish this.
Thanks in advance
function imageList(mcname, img, index){
var imgMcA:MovieClip=new MovieClip();
imgMcA.graphics.beginFill(0x000000);
imgMcA.graphics.drawRect(0,0,imgWidth,imgHeight);
imgMcA.graphics.endFill();
imgMcA.name=lemma;
imgMcA.addEventListener(MouseEvent.CLICK, moveImage);
var imgMcB:MovieClip=new MovieClip();
imgMcB.graphics.beginFill(0x000000);
imgMcB.graphics.drawRect(0,0,imgWidth,imgHeight);
imgMcB.graphics.endFill();
imgMcB.name=index;
addChild(imgMcB);
var imgLoader:Loader = new Loader();
imgLoader.load(new URLRequest(img));
imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, changeProperties);
imgLoader.mouseEnabled=false;
imgMcA.addChild(imgLoader);
}
function moveImage(evnt:MouseEvent){
}
You could linked mcA & mcB by adding them to the same parent.
function createBlock():void
{
var imgLoader:Loader = new Loader();
//add the loading code here...
var mcA:Sprite = new Sprite();
var mcB:Sprite = new Sprite();
// add Click event listeners for both Mcs here...
var parent:Sprite = new Sprite();
//add Children
parent.addChild(mcA);
parent.addChild(mcB);
addChild(parent);
}
function mouseClickHandler(event:MouseEvent)
{
var dispatcher:Sprite = event.currentTarget as Sprite;
//if you added a Loader to it
if( dispatcher.numChildren > 0)
{
//retrieve the image
var img:Loader = dispatcher.getChildAt(0);
//identify the parent
var parent:Sprite = dispatcher.parent;
var index:int = parent.getChildIndex(dispatcher);
//identify the receiving MC
//of course this only works with two children!!!
if(index > 0)
var receiver:Sprite = parent.getChildAt(0) as Sprite;
else
receiver = parent.getChildAt(1) as Sprite;
//add the image to the other MC
receiver.addChild(img);
}
}
The rest is not too complicated to achieve. You will need to use a Boolean and add a TextField. If the TextField contains text, set the Boolean to true.
It may be worth looking at Classes or you could use an Object as a container for the MovieClips, the TextField and the Boolean, although a Class will give you more flexibility...
With a Class, you wouldn't have to iterate in order to find what does what. Your Click listener would look something like this:
private function mouseClickHandler(event:MouseEvent)
{
receiver.addChild( image );
if( hasText)
imageReturn();
}

TextField breaking MOUSE_OVER after moving it

I'm having a really weird problem with the MOUSE_OVER event. I'm building dynamic tabs representing mp3 songs containing textfields with info and a dynamic image for the cover art. I am trying to get a simple MOUSE_OVER working over the whole tab, such that you can select the next song to play.
I am using a Sprite with alpha 0 that overlays my whole tab (incl. the textFields) as a Listener for MOUSE_OVER and _OUT... I've checked by setting the alpha to something visible and it indeed covers my tab and follows it around as I move it (just making sure I'm not moving the tab without moving the hotspot). Also, I only create it once my cover art is loaded, ensuring that it will cover that too.
Now, when the tab is in the top position, everything is dandy. As soon as I move the tab to make space for the next tab, the textFields break my roll behaviour... just like that noob mistake of overlaying a sprite over the one that you're listening for MouseEvents on. But... the roll area is still on top of the field, I've set selectable and mouseEnabled to false on the textFields... nothing.
It is as if the mere fact of moving the whole tab now puts the textField on top of everything in my tab (whereas visually, it's still in its expected layer).
I'm using pixel fonts but tried it with system fonts, same thing... at my wits end here.
public function Tab(tune:Tune) {
_tune = tune;
mainSprite = new Sprite();
addChild(mainSprite);
drawBorder();
createFormat();
placeArtist();
placeTitle();
placeAlbum();
coverArt();
}
private function placeButton():void {
_button = new Sprite();
_button.graphics.beginFill(0xFF000,0);
_button.graphics.drawRect(0,0,229,40);
_button.graphics.endFill();
_button.addEventListener(MouseEvent.MOUSE_OVER, mouseListener);
_button.addEventListener(MouseEvent.MOUSE_OUT, mouseListener);
_button.buttonMode = true;
mainSprite.addChild(_button);
}
private function mouseListener(event:MouseEvent):void {
switch(event.type){
case MouseEvent.MOUSE_OVER :
hilite(true);
break;
case MouseEvent.MOUSE_OUT :
hilite(false);
break;
}
}
private function createFormat():void {
_format = new TextFormat();
_format.font = "FFF Neostandard";
_format.size = 8;
_format.color = 0xFFFFFF;
}
private function placeArtist():void {
var artist : TextField = new TextField();
artist.selectable = false;
artist.defaultTextFormat = _format;
artist.x = 41;
artist.y = 3;
artist.width = 135;
artist.text = _tune.artist;
artist.mouseEnabled = false;
mainSprite.addChild(artist);
}
private function placeTitle():void {
var title : TextField = new TextField();
title.selectable = false;
title.defaultTextFormat = _format;
title.x = 41;
title.y = 14;
title.width = 135;
title.text = _tune.title;
title.mouseEnabled = false;
mainSprite.addChild(title);
}
private function placeAlbum():void {
var album : TextField = new TextField();
album.selectable = false;
album.defaultTextFormat = _format;
album.x = 41;
album.y = 25;
album.width = 135;
album.text = _tune.album;
album.mouseEnabled = false;
mainSprite.addChild(album);
}
private function drawBorder():void {
_border = new Sprite();
_border.graphics.lineStyle(1, 0x545454);
_border.graphics.drawRect (0,0,229,40);
mainSprite.addChild(_border);
}
private function coverArt():void {
_image = new Sprite();
var imageLoader : Loader = new Loader();
_loaderInfo = imageLoader.contentLoaderInfo;
_loaderInfo.addEventListener(Event.COMPLETE, coverLoaded)
var image:URLRequest = new URLRequest(_tune.coverArt);
imageLoader.load(image);
_image.x = 1.5;
_image.y = 2;
_image.addChild(imageLoader);
}
private function coverLoaded(event:Event):void {
_loaderInfo.removeEventListener(Event.COMPLETE, coverLoaded);
var scaling : Number = IMAGE_SIZE / _image.width;
_image.scaleX = scaling;
_image.scaleY = scaling;
mainSprite.addChild (_image);
placeButton();
}
public function hilite(state:Boolean):void{
var col : ColorTransform = new ColorTransform();
if(state){
col.color = 0xFFFFFF;
} else {
col.color = 0x545454;
}
_border.transform.colorTransform = col;
}
Fixed it. What was happening was that I didn't set the height of the textfield. That was overshooting the tab and hence lying over the previously instantiated tab, blocking MouseOver... don't even ask.