Forum Thread
  Posts  
(Java) JLayeredPane, JPanels and Images (Forums : Coding & Scripting : (Java) JLayeredPane, JPanels and Images ) Locked
Thread Options
iqew
iqew VFX Artist
Mar 27 2013 Anchor

Hey guys,

just wanted to know, whether it's somehow possible to have a JPanel on a JLayeredPane, which has the paint method overwritten to draw a graphic on it. The idea behind all that is to have a automatically scrolling background image (game background), which is just repainted to the JPanel with a Timer. But, I was wondering, whether it might now be possible to have other GUI stuff on top of that scrolling background (imagine "in-game" action in a main menu in the background).

I have googled and looked through forums, the api, experimented and all that, but couldn't figure out a solution yet. I'm only in the 2nd semester in college, but I'd really like to see this working somehow (just a moving background with buttons on-top). If JLayeredPanes aren't the right choice, I'd like to know about how you guys would do it.

Best wishes
Kjell

Dragonlord
Dragonlord Linux-Dragon of quick wit and sharp tongue
Mar 27 2013 Anchor

Don't overwrite the paint method. It's a meta-method so to speak which delegates to the three hook methods paintComponent,
paintBorder
and paintChildren in exactly this order. If you overwrite paint you mess this all up. What you actually want is modifying the painting of the component itself leaving the border or children painting alone (drawing your children buttons). Hence what you want is overwriting paintComponent. The most safe solution is to call super.paintComponent(g) in there before doing your own painting to get the housekeeping properly intact. Obviously you can do all the work on your own if you know what you are doing to get the most speed out of it.

So in a nutshell:
1) make a subclass of JPanel
2) implement paintComponent to draw your background

There exist more complex solutions avoiding the need to implement the paintComponent method by using a nested JPanel stacked with an image component. The stack layout manager keeps your sub-panel in place relative to the parent panel while the image can be shifted around. But this requires some book keeping and might be a bit too much for a 2nd semester code base so try to get the paintComponent version working. Of course if you like an additional excercise see if you figure out the nested panel version on your own.

Edited by: Dragonlord

iqew
iqew VFX Artist
Mar 28 2013 Anchor

Dragonlord wrote: Don't overwrite the paint method. It's a meta-method so to speak which delegates to the three hook methods paintComponent,
paintBorder
and paintChildren in exactly this order. If you overwrite paint you mess this all up. What you actually want is modifying the painting of the component itself leaving the border or children painting alone (drawing your children buttons). Hence what you want is overwriting paintComponent. The most safe solution is to call super.paintComponent(g) in there before doing your own painting to get the housekeeping properly intact. Obviously you can do all the work on your own if you know what you are doing to get the most speed out of it.

So in a nutshell:
1) make a subclass of JPanel
2) implement paintComponent to draw your background

There exist more complex solutions avoiding the need to implement the paintComponent method by using a nested JPanel stacked with an image component. The stack layout manager keeps your sub-panel in place relative to the parent panel while the image can be shifted around. But this requires some book keeping and might be a bit too much for a 2nd semester code base so try to get the paintComponent version working. Of course if you like an additional excercise see if you figure out the nested panel version on your own.


Thanks for your answer! I have another question though, you're mainly talking about the mistake that I made, but can you also tell me, whether it makes sense to use JLayeredPane? Wouldn't it be possible to have an image displayed at a deeper level than the menu is? The only problem I had was that I was only able to use a JLabel with an ImageIcon. But, I wanted to stick with the way to draw an image onto the JPanel, which makes it easy to make it move. However, when I went for a JPanel with a drawn image onto it, it wasn't displayed in the JLayeredPane at all.

And, another question: what's a stack layout manager? Didn't really understand what you you wanted to tell me there :/

Best wishes
Kjell

--

Need some polishing for your game with beautiful VFX? Check out my website: Game-vfx.com

Dragonlord
Dragonlord Linux-Dragon of quick wit and sharp tongue
Mar 29 2013 Anchor

iQew wrote: I have another question though, you're mainly talking about the mistake that I made, but can you also tell me, whether it makes sense to use JLayeredPane? Wouldn't it be possible to have an image displayed at a deeper level than the menu is? The only problem I had was that I was only able to use a JLabel with an ImageIcon. But, I wanted to stick with the way to draw an image onto the JPanel, which makes it easy to make it move. However, when I went for a JPanel with a drawn image onto it, it wasn't displayed in the JLayeredPane at all.

JLayeredPane does as the name suggests layers groups of components one over the other. Windows are typically done this way to layer the menu and toolbars over the content. Now layers are though also all children components and thus they are all drawn after paintComponent has been invoked. You can thus use JLayeredPane or a JPanel for this task since in both cases paintComponent is the very first drawing happening to your component. If you draw there your image using Graphics you are all set.

As mentioned above you can use a nested version to layer your children components over your image component. This avoids the need to overwrite the paintComponent method and is the better albeit a bit more complex solution. JLayeredPane is one possibility to get the job done but it has been designed foremost for use with Window components and thus the layers are fixed and have a special meaning. The better solution is to use a proper stacking layout.

what's a stack layout manager?

Java separates the layout from the hierarchie. A JPanel with its children is the hierarchie while the LayoutManager object defines how these children are laid out. A stacking layout is thus a LayoutManager placing all children components one over the other with their size filling the entire parent component. In this case this is the javax.swing.OverlayLayout class. The best way to do this is to use a panel containing two stacked panels one for the background and one for the content. This would look roughly like this (out of my head, mistakes are possible):

parentPanel = new JPanel();
parentPanel.setLayout( new OverlayLayout( parentPanel ) );

// provides a simple way to move a component looking only at a viewport of it.
panelBackground = new JViewport();
parentPanel.add( panelBackground );

// the actual content of the background to scroll.
panelBackgroundContent = new JPanel();
// TODO: set layout for background and add images, texts, whatever.
panelBackground.setView( panelBackgroundContent  );

// all the rest going ontop of it
panelContent = new JPanel();
// TODO: set layout for panel content and add buttons, whatever that goes over the background.
parentPanel.add( panelContent );

You can then scroll the background content JPanel around using panelBackground.setPosition( new Point( x, y ) ). This one should do the trick without the need to fiddle with overwriting methods. Both versions though should be a good exercice.

EDIT: I forgot to say that you need to set the background property of the JPanel going ontop of all to transparent otherwise it won't show what is underneath. JPanels are bei default opaque.

Edited by: Dragonlord

Reply to thread
click to sign in and post

Only registered members can share their thoughts. So come on! Join the community today (totally free - or sign in with your social account on the right) and join in the conversation.