I'm working on a game that uses mx canvases (each in their own mxml file) to wrap different aspects of the application. So the UI is wrapped in one canvas, the main game screen in another, and so on. I am having an issue where mouse input (specifically MouseEvent.CLICK, but it seems to apply to all mouse input) that I want to go to a movieClip in the GameScreen.mxml is being caught by an mx.core.FlexSprite object called "contentPane" that is a child of the GameUI.mxml.
This contentPane sprite doesn't exist when the GameUI object is instantiated, and in fact doesn't seem to exist until I set the text of some textFields contained by the GameUI. These textFields do overlap the movieClip that I want to receive the mouse input, but the textFields themselves are set to mouseEnabled = false, and are not catching the mouse input.
None of my code is directly creating this contentPane sprite, and some elementary Googling tells me that this contentPane sprite is created by the mx.flex.container internally. However, I can't seem to find any documentation on how this actually works, and what causes this sprite to be created.
This functionality has worked previously, and the only significant recent change I'm aware of is moving the swfs loaded into the GameUI into their own application domain to fix a namespace collision. I'm entirely prepared to believe that is the issue.
Ideally, I'd like to know why this contentPane is suddenly catching mouse input. Failing that, I'd at least like to find some documentation on how contentPane works, how I can manipulate it, and what causes its instantiation.
Thank you in advance for your help.
Edit:
I've done some additional digging and wanted to share what I've learned:
The contentPane variable is instantiated in mx.core.container objects for scrolling and clipping purposes. If the content of an mx.core.container object exceeds the size of that object, the container will create a contentPane and move its contents into that pane. However, if scrolling is disabled (verticalScrollPolicy="off" & horizontalScrollPolicy="off") and clipping is disabled (clipContent="false") then the container will not instantiate the contentPane. This solved my specific problem as I did not need either scrolling or clipping behavior in this container.
I would still like to know if there's a way to disable mouse input for an mx.core.container contentPane. It seems like there should be.
Related
i am working with several nested movieclip objects in a project. but i get into trouble with the buttons i created and implemented in the nested movieclips:
to describe it in a simple way:
I have a main movieclip with five frames, including two buttons with listeners to browse between the frames. Then inside of one Frame I have another movieclip with its own buttons. i instanciated it by hand not through code and gave it a specific name like "nestedMc".
Now I dont want to build the Listeners for those buttons inside the class of the nested movieclip class but in its parent class, which works fine until i then goto another frame in the main movieclips timeline and come back.
obviously every time flash enters a frame its contents get created anew (and therefore get new instance names). I could now try solve this through filling the frames via code.
But maybe there is another way to make sure the frame contains the same instance everytime i enter?
Timeline scripting is a dirty business, and really, a carry-over compatibility layer for Actionscript 2 projects. Whenever possible, I highly recommend not doing it, and simply keeping all of your code in your document class. As you're experiencing, timeline code causes headaches.
Consider instead just creating both states of your Stage (it sounds like that's what your two buttons are jumping between) and simply hiding them offstage or setting their alpha to zero and their mouseEnabled state to false. Furthermore, if the purpose of your frames is to play animation (a tween), consider instead switching to a much more powerful suite such as TweenLite. Moving an object over a hundred pixels (smoothly) can be as easy as:
TweenLite.to(redBall, 3, {x:100});
Now, if you're manually adding these items to the stage, as long as the object is a dynamic one, you can assign an instance name to it which will be saved between frame loads. Be aware the object name is not the same as the instanced name. For example:
var redBall:Ball = new Ball();
redBall.name = "bubbles";
The object's name is Ball, but it's represented as a variable called redBall. Its actual DisplayList name will likely be ambiguous (such as "Instance71"), and I can manually define it as "bubbles". 3 different names for the same object, all very different and necessary.
Even if you give the object a displayList name, you may not be able to reference it through code unless you enable Automatically declare stage instances, which basically creates on each object a pointer to the displayList object.
That said, you can always fetch the object by other means. Obviously, your buttons are always appearing, but you're trying to find a very specific object on the stage. At this point, we can use getChildByName() or getChildAt().
Hope that helps.
-Cheers
Having read many tutorials, articles and questions, I am still have confusions about updating the GUI. Plus there are numerous related questions here on this website and still no luck - even though I think my problem is very simple.
Basically, I have a JFrame that has a JLayeredPane as its root container. And I have some layers of JPanels inside it.
The main issue is with updating a particular JPanel in this JLayeredPane. And for this particular Panel, I have implemented an update method that changes the contents inside it.
updatePanel(int para)
//doesn't remove this panel
//removes some existing labels and replaces it with new ones
Once I create the whole Frame, obviously just calling this method won't show any change displayed the frame.
private void static main (String[] args){
WindowFrame frame = new WindowFrame()//WindowFrame extends JFrame
frame.updatePanel(2);
.....
.....
}
And that's where I am stuck. I want to update the contents as the frame is displayed.
I saw these methods mentioned by people but due to nature of problems, I couldn't fully grasped the concepts. Plus the documentation on these methods isn't really helping - at least to me.
revalidate()
validate()
repaint()
How/when should these methods should be called? Or is this not the right way of what I should be doing, given these methods and the problem I am trying to solve?
Thank you for your time.
Basically you need two methods:
revalidate()
This method does the same as invalidate() but in AWT event dispatching thread (i will just call it Swing thread later on)). It updates container and all of its ancestors (parent containers in which this one is placed) layouting.
Basically if you either move something inside this container or place/remove components inside of it you should call this method (or invalidate in case you are performing it in Swing thread, for example inside any Mouse/Action listener body or just inside).
repaint()
This method forces component, all its sub-components (if it has them) and parent container (basically if this component is NOT opaque) to update what they are "painting".
Usually you don't need this method since all standard Swing components know when to repaint themselves and they do it on their own (that ofcourse depends on components UIs and some other things). This method might be useful in case you have your own specific components with some unique painting-way (for e.g. some custom selection over the components) and in some rare problematic cases with standard components.
Also the way this method acts depends on the components placement (due to some Swing painting optimizations) - if you have some massive repaints rolling you'd better optimize them to repaint only those parts (rects) that you actually need to repaint. For example if you change the component bounds inside any container the best choice is either to repaint its old bounds rect and new bounds rect OR repaint rect that contains both of those bounds, but not the whole container to avoid repainting uninvolved in the action components.
So, basically in your case after some changes with panels you should call revalidate on their container (or invalidate) followed by repaint (in case revalidate leaves some visual artefacts) again for the container.
Guess i didn't miss anything and i hope that now you know the basic meaning of those methods.
revalidate at the end of your update method like so .
updatePanel(int para){
.....
.....
this.revalidate(); //of course this refer to the panel
parent.revalidate(); // parent refer to the window
}
There was many discussions about this problem, but I want to pay attention on the situations that IMHO seems not so clear:
Yes the general rules are:
Remove chachedAsBitmap
Stop movieClip if playing
Remove events
Delete references
etc.
But let's look:
First Example:
I have nested sprite (ex: mainSprite), it contains other sprites with dynamic textFields in it (and are chached as bitmaps), just textFileds and MovieClips with event listeners on it (with weak reference).
When I need to remove this sprite I need first to remove all it's nested content via loops or just
removeChild(mainSprite);
mainSprite=null;
is just enough?
Second Example:
I have some sprite in which I'm loading bitmap and manipulating with bitmapData, later I'm just replacing content of this sprite with another bitmap, is allocated memory for older bitmap automatically erases and is overwritten or it still exists?
Third example:
I have some "graphics template" MovieClip (in library with Export for Actionscript property set on it) which I'm adding on the stage and filling with dynamic data (and adding event listeners), let's say that it's one scene of the app, on another scene I need same MovieClip with other dynamic data, but inbetween need to clear my stage (need something like transition animation which is also library MovieClip), what's the best way: to set this MovieClip visible property to false (while transition animation is plays) and then reuse it, or just remove it with removeChild and then add when add with addChild once more?
All I wrote is more about Air Mobile, cause in most cases for the desktop these situations aren't so problematic, but in case of mobile development they are.
You can visually monitor memory usage along with fps etc using this lib: http://code.google.com/p/flash-console/
hope that helps.
P.S. gc in flash is always a weird thing :)
First example: removing mainSprite from display list is enough if there are only weak listeners on its children.
Second example: I'd advice reusing the same object with visible = false. Recreating the same object is more resource expensive plus you get another instance of the same thing being in memory before it gets gc'ed.
I'm having an issue with Movieclips inside my Swf resizing to the wrong dimensions. I'm currently tracing the width of the offending clip every half second, and I can see the value change to an incorrect size at some interval in the logged output. I really want to see what code is changing the width. My plan was to extend Movieclip, override the set width property, and dump a stack trace when the value set is too low. This isn't so simple however. Flash is complaining about undefined reference to UI components that are on the Movieclip fla.
Is there a simple way to find out when/why this value changes? I cannot use a debugger.
edit:
The reason I cannot just extend MovieClip is because I am getting my Movieclip object from Event.currentTarget.content after using a Loader. I cannot point my Test (extends MovieClip) object at this return value because it is illegal to do so.
I'll explain the problem a little more and maybe someone will have another idea. I have an app with lots of different windows. They all open to a size of around 750x570. One of these windows contains a FusionChart. when I load this, according to my trace, the background Swf I am using changes to a dimension of about 2712x1930. This doesn't make sense to me because it looks the same size as before and at those dimensions it wouldn't even come close to fitting on my screen. If I then close the window and open another, the new window is tiny, but says it has the same dimensions as the original windows (750x570).
It is almost as if the window is scaling to the huge 2712x1930 without showing a change in size, and then showing the next window (750x570) as a size relative to what the huge window would look like. If that makes sense...
Maybe using a Proxy?
The Proxy class lets you override the default behavior of ActionScript operations (such as retrieving and modifying properties) on an object.
If you can see the trace you are doing and use a debug version of the flash player, try to override the property you want to check and trace the calling stack stack within the Error object:
public class Test extends Sprite() {
// property to watch
override public function set x(value:Number):void{
super.x=value;
// trace the calling stack work only in the flash debug player
trace((new Error()).getStackTrace());
}
}
what do you mean by "Flash is complaining about undefined reference to UI components that are on the Movieclip fla."?
your idea is absolutely the right solution in general... assuming the property doesn't change from within the runtime (which is rare, unless those properties are calculated) ...
when it comes to width and height, they are the two worst properties in the flash player API ... for reading, they are calculated by the space needed by a DisplayObject in parent coordinate space (if you rotate a DisplayObject, than these properties change). for writing, they actually forward to scaleX and scaleY ...
I am creating a photo editor app where, at some point, the photo you edit is supposed to be dropped between two layers of DisplayObjects (a background image and an image mask.)
There is a problem, though. When the image you are editing is dropped between the background and the image mask layers, it becomes unclickable, and therefore gets stuck there, with no chance of dragging it again. (The photo editor uses TransformManager library.)
I am looking for a way to allow you to select the image you are editing no matter if there is another DisplayObject on top of it. And that probably means finding some way to click through the image mask.
Is there a way to do that?
I tried setting mouseChildren = false on imageMask, but that didn't have the desired effect.
Many thanks.
I had similar problems and I managed to solve it by using both
displayobject.mouseChildren = false;
and
displayobject.mouseEnabled = false;
on the object that you want to click through.
How about this?
mask.mouseEnabled = false;
You can always attach a Mouse Click listener to the container, and then either use GetObjectsUnderPoint and check for your object or do a hit test and see if the mouse position is over your intended object.
The hit test would look something like this !this.YourPhoto.hitTestPoint(stage.mouseX, stage.mouseY, false)
b
If I understand your problem, this handy class should solve it:
http://www.mosessupposes.com/utilities/InteractivePNG.html
Take a look at what senocular does here, specifically in the handleUpdate method. Basically: getting a list of everything under the mousePoint to find your object.
I think I stumbled upon similar problem, although in as2.
In flash when you position movie clip over movie clip, and the movie clip on the top has any mouse events implemented, it captures all mouse events so they never reach occluded movie clip.
The solution is not to have any mouse events for the top movie clip and have the movie clip positioned at the bottom capture mouse event and redirect some of them to the top movie clip (you can check mouse position with hitTest to determine if they should be redirected).
i had a strange bug i used;
movieClip.mouseEnabled = false;
but wasn't working for some reason.. was driving me crazy!! as i have used it so many times before. tried lots of different things nothing worked then i deleted the MovieClip and the created a new one and worked.. so the MovieClip's contents must have been corrupt or something as it had a old dynamic Text Area box embedded within the MovieClip.
hope this helps someone out there..