I have a scrollpanel test headers in it. Through debug, I see that the panel itself is there, but the content is not displayed in it, although it seems to be. Maybe someone knows how this is possible? The panel itself adjusts to the size of the table, but the table itself, with the content inside, is not visible.
I found the root cause of the issue - you incorrectly added the actors to the stage, which resulted in Window's and ScrollPane's Stage to be null. You have to change this line in GameManager:
screen.rootStage.actors.add(inventoryWindow.window)
To this line:
screen.rootStage.addActor(inventoryWindow.window)
While your approach did add the actors to the Stage, they were not added to the root Group and their Stage variable was not set, which resulted in weird bugs like this one. Always prefer to use the public API methods instead of accessing the class variables directly.
About pinpointing the issue: if you look into the ScrollPane rendering code, you'll notice that it only renders it children if clipBegin returns true. If you dig deeper, clipBegin has this particular check that prevented the children from being drawn: if (stage == null) return false;. Basically, you cannot use a ScrollPane without a Stage.
Related
I have a UI object that, of course, should always be kept in front of all other objects. To do that, I decided to destroy and add it again each frame, like this:
removeChild(UI_Indicator)
addChild(UI_Indicator)
But nevertheless, objects that are created in it’s area still come on top of it. How is this even possible? I also tried the common
UI_Indicator.parent.setChildIndex(UI_Indicator,UI_Indicator.parent.numChildren - 1)
But it doesn’t work too. Any suggestions?
You are not destroying anything with removeChild(), you just stop displaying it. removeChild() isn't even necessary here. addChild() happily takes a DisplayObject that is already a child of the DisplayObjectContainer you called it on and re-adds the child again (to the top)
Instead of doing this readdChild()ing every frame, place your
allways-on-top DisplayObject on the display list once, then create
a DisplayObjectContainer, say a Sprite for example and add it
behind your indicator. Now add all your other DisplayObjects to
that container. This has the disadvantage of requiring you to add
everything to the container. The functionality breaks as soon as you
accidentally addChild() the regular way. This thought process
leads to the second solution below.
In your subclass of DisplayObjectContainer that includes the
indicator, override the methods that interact with the display list
(add/remove children, etc.) All those that could cause something to
get on top of your indicator. This puts you in full control of
what's going on when something is added to this container. You can
either incorporate solution 1 for simplicity's sake: delegate all
method calls to the inner container Sprite or, if you don't like
to have an internal container, do it without it and make sure that
no other child than your indicator is ever assigned the top most
index. You'd create an additional method to add the always-on-top child, like addTopChild() for example.
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.
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
}
Before I go making major change in my ongoing game project, I just want to hear from others if anyone has found any issues with getObjectsUnderPoint() function of the DisplayObject?
Update:
Not just the performance issue but any other limitations of using it (like it doesn't detect certain type of UIelements (just as example))
I will have three layers in my application (which an Isometric game)
Background -- This is just a background which stays in the bottom, has nothing to do with game
Middle Layer -- This is the playable area, Here all my game elements will be placed on this layer
Top Layer -- This is one dummy transparent layer covers entire playable area which interrupts all the mouse events. This is where I want to use the getObjectsUnderPoint()
So, player wants to click on the element, the top layer will interrupt the mouseevent and then check if there is something placed or just a plain background and take appropriate action like, notify the underneath object.
This really doesn't require to be done this way because I could simply add moues events for all those items placed on the map directly but because I would be using getObjectsUnderPoint() anyway to check if there is anything beneath the item.
If anyone can explain how this function works then it would be little easy for me to make a decision.
There was one annoying problem though. I don't know if they fixed it or not. At least it was there in 10.1 times.
If you have a container and you scaled it container.getObjectsUnderPoint will return wrong result. All the time. So everywhere where I needed getObjectsUnderPoint I had to call it from stage to get proper result.
It's an incomplete function. It returns graphical objects under the mouse, NOT all potential mouse targets for event or interaction purposes. It actually requires complex logic to examine the array returned by getObjectsUnderPoint to determine the mouse target, because the appropriate target (the one Flash would choose if you actually clicked that point) may not be in the list.
First you'd have to examine the object array in reverse, since the items are ordered back to front. You'd have to examine each object's entire parent chain, looking for a parent with mouseChildren = false that would cause it to intercept the event and become the target. Whether or not such an object is found, this final object you arrive at must have its mouseEnabled property set to true, otherwise you must skip it and move on to the next object in the array, which would be, for example, the next sprite or shape behind the one you initially checked. While going through the list, you must notice when the parent changes, at which point you need to assume that all children of that common parent had their mouseEnabled property set to false, in which case the parent would become the next candidate. This is actually extremely complicated, because you're working backwards in a bottom-up approach with an incomplete set of objects that was generated from the top-down.
To get actual potential mouse event targets, consistent with the default dispatching logic... it is actually easier to start from the stage in a top-down manner and walk backwards through the display hierarchy in a depth-first search, checking mouseChildren to determine whether you need to step into children, and checking mouseEnabled if it's to be a target, otherwise stepping into the container's children and repeating the process from back to front again. This is much more accurate, complete, and staightforward. The only problem is you have to code it yourself.
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 ...