How to animate showing of JPopupMenu? - swing

I'd like to show increasingly more of a JPopupMenu so it appears to "slide out". It's not for menu items, where animation doesn't make too much sense. Instead it's for a panel with some real components (oh yeah, you can add any JComponent to JPopupMenu).
JPopupMenu has many private fields and methods, which makes it hard to extend. Plus I'm not familiar with Swing animation to begin with.
Thanks a lot for your help!

I just did this within the last few weeks. I went a slightly different approach, and Grabbed the layeredPane, and then added a Custom JPanel to the layered pane. In the jpanel i overrode the getHeight method, and had the height start at 0. I could then add whatever components I wanted to my jpanel. In the jpanel I had a method to start animation, this started a timer, and in the timer all I did was increase the height of my jpanel to a max size.
That's it. It works really well in my application, I have it tied to expand below a Jbutton on press, and collapse on another press.
One more thing, you'll want to add a mouseAdapther to the jpanel so events don't go through the components below the layer.

Related

Easiest way to implement a game menu in ActionScript 3?

At the moment my game simply consists of a play button which, when clicked, runs the game; all of this happens in the document class as follows:
stage.addChild(playBtn);
playBtn.x = 0;
playBtn.y = stage.stageHeight/2;;
playBtn.addEventListener(MouseEvent.CLICK, playGame);
The playGame() function then removes playBtn from the stage and the event listener, and runs the game code. This has been fine for me up until now, but now I want to implement a more complex menu system, which will probably consist of many buttons, graphics, etc (basically a stage select screen). My question is, what would be a more efficient way of displaying a menu on the screen, removing it when a stage is selected and then being able to return to the menu when the game is over? Obviously I'm trying to do all of this without the use of the timeline.
Use separate classes for each screen. For example a MainMenu screen class and a Game class. Then your document class becomes a simple screen switching controller, which instantiates, adds and removes screen classes.
As long as each screen only adds content into itself, and not to the stage, the document class need not know or care what's inside the screens, and removing a screen will not require each element in the screen to be removed.
As for how to add all elements to each screen, let the screen class handle it, or a symbol linked to the screen class with all your content.

Problems with contentPane in mx.flex.container eating mouse input

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.

How to updating JLayeredPane while the JFrame is running ? java

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
}

How to add any Component in the JFrame TitleBar

How to add any Component like a JButton on the JFrame TitleBar in java swing.
I assume by "title bar" you think of the header with the window menu button, document or program title and buttons for (typical) maximize, minimize, close.
The window borders are drawn by the operating system (whatever part, e.g. with XServer it would be a window manager most of the time) - usually. And this is what the user wants - usually. Then this part of the window is outside the reach of Swing, you need to add components by native code (JNI or one of its nicer wrappers like JNA).
But you can set a Frame to undecorated via setUndecorated. This leaves the whole window area in your responsibility, you have to draw everything yourself and care for things like draggability of the window. Think of a completely "skinned" application. If the look and feel you use supports drawing of the windows borders (javax.swing.LookAndFeel#getSupportsWindowDecorations()) you don't have to do this yourself but set JFrame.setDefaultLookAndFeelDecorated(), the LookAndFeel will draw the border with Swing components. Then you can add Swing components either by glasspane or by changing the component that draws the title bar.

How to auto resize JFrame according to content

I have created a custom JPanel that displays images (lets call it MyPanel), I have added this to JFrame's contentPane.
I want JFrame to be resized automatically to fit the MyPanel when image changes.
It looks like I need to call frame.pack() to do this. Calling pack() from MyPanel increases coupling so I don't want to do that.
To solve the issue I extended JFrame (lets call it MyFrame) and made MyFrame observer, and MyPanel observable. Whenever the image MyPanel is displaying changes it notifies the listeners, MyFrame for this instance. And then MyFrame calls pack() when it gets the notification.
Is there a smoother way of resizing JFrame according to its content?
The solution you described seem reasonable.
Alternatively, whenever MyPanel changes its image, it can go find its parent Frame and then call pack() on it. If no such Frame exists, then don't do anything. No need to create additional classes, and its as loose a coupling as you are going to get. You can use SwingUtilities.getAncestorOfClass() to do this easily.