[java] hideable panel

Recommended Posts

kratz    134
Could someone tell me the best way to have reuseable panels in my game? I have a panel with a START button and some radio buttons for selecting game difficulty. When the game starts I just hide the panel using panel.setVisible(false); but when I'm ready to use the panel again using panel.setVisible(true) the panel doesn't accept input from the mouse like my Listener quit listening. I'll also want to do the same sort of thing for an in-game menu. Can anyone help me out? Thanks kratz

Share on other sites
Giuoco    145
You might have to set the focus on that panel... Maybe look in the api doc's for the requestFocus() method of awt component.

Good luck!

Share on other sites
Hi,

I'm not sure why that would not work for you. It appears to work fine when I tried it.

import java.awt.*;import java.awt.event.*;import javax.swing.*;import javax.swing.border.*;import java.util.*;public class HiddenPane extends JFrame implements ActionListener {		private java.util.Timer tasker = new java.util.Timer();	private JPanel hiddenPane = new JPanel( new FlowLayout() );		public HiddenPane() {		super("Hidden Pane Example");				MouseMotionListener mml = 			new MouseMotionAdapter() {				public void mouseMoved( MouseEvent e ) {					System.err.println("Mouse Move Over Component Detected");				}			};				JButton start = new JButton("Start My Game Man");		JButton gimme = new JButton("Gimme The Money Biotch");		JButton quit = new JButton("Leave This Trash");		start.addActionListener(this);		start.addMouseMotionListener(mml);		gimme.addActionListener(this);		gimme.addMouseMotionListener(mml);		quit.addActionListener(this);		quit.addMouseMotionListener(mml);				hiddenPane.setBorder( new EmptyBorder(100,0,100,0) );		hiddenPane.add(start);		hiddenPane.add(gimme);		hiddenPane.add(quit);		hiddenPane.addMouseMotionListener(			new MouseMotionAdapter() {				public void mouseMoved( MouseEvent e ) {					System.err.println("The Mosue Moved On My Panel");				}			}		);				getContentPane().add(hiddenPane);				hiddenPane.setVisible(false);				tasker.schedule( 		 	new TimerTask() {		 		public void run() {		 			hiddenPane.setVisible(true);		 		}		 	}, 5000);				addWindowListener(			new WindowAdapter() {				public void windowClosing( WindowEvent e ) {					exit();				}			}		);		setSize(640,480);		setVisible(true);	}		public static void main( String args[] ) {		new HiddenPane();	}		public void exit() {		setVisible(false);		dispose();		tasker.cancel();		System.exit(0);	}		public void actionPerformed( ActionEvent e ) {		String cmd = e.getActionCommand();				if( cmd.compareTo("Start My Game Man")  == 0 ) {			System.err.println("start");		}else if( cmd.compareTo("Gimme The Money Biotch") == 0 ) {			System.err.println("extras");		}else if( cmd.compareTo("Leave This Trash" ) == 0 ) {			System.err.println("quit");			exit();		}		System.err.println("There was an action trapped");	}	}

Make sure that you are creating and adding the listeners to the components that you want to be able to receive event messages. Also make sure that the Panel is added to the ContentPane of the JFrame it's supposed to be in.

Hope this helps! If you can't find the problem post some of your code and I'm sure someone will be able to find the problem.

Share on other sites
kratz    134
Hey 5minute thanks for your reply. I finally got the beginning menu to work but I have some questions about your code. 1. Is it better to call addListener on everything or does an addListener on the parent JFrame automatically apply to all the visible child components?
2. I read somewhere that in 1.5 that adding to the contentPane is now the same thing as just adding to the parent frame. Is this true or is there an advantage to using getContentPane().add?
I'm still working on the in-game menu without much success at all. I'm addin the panel like this in my setupGUI function

        inGamePanel = new JPanel(layout);        inGamePanel.setSize(75, 75);        inGamePanel.setBackground(Color.black);        inGamePanel.setVisible(false);        quitButton = new JButton("Quit Game");        inGamePanel.add(quitButton);       	inGamePanel.setLocation(width/2, height/2);        this.getContentPane().add(inGamePanel);

then I show the panel in my renderPaused function like this

    	 // clear offscreen canvas        g.setColor(Color.black);        g.fillRect(0, 0, width, HUD_HEIGHT);        g.drawImage(background, 0, HUD_HEIGHT, width, height, this);         g.setColor(Color.BLUE);        g.setFont(scoreFont);    	g.drawString("PAUSED", width/2-75, height/2);    	        paintAll(g);      //Try to show the ingame menu    	g.dispose();    	strategy.show();

well it erases my whole scene THEN shows the panel which is obviously not what I want. I guess I'm just having a hard time understanding how Swing paints things.

Any suggestions?
Thanks
kratz

Share on other sites
Quote:
 Original post by kratz // clear offscreen canvas g.setColor(Color.black); g.fillRect(0, 0, width, HUD_HEIGHT); g.drawImage(background, 0, HUD_HEIGHT, width, height, this); g.setColor(Color.BLUE); g.setFont(scoreFont); g.drawString("PAUSED", width/2-75, height/2); paintAll(g); //Try to show the ingame menu g.dispose(); strategy.show();well it erases my whole scene THEN shows the panel which is obviously not what I want. I guess I'm just having a hard time understanding how Swing paints things.Any suggestions?Thankskratz

There was a similar problem in this post: http://www.gamedev.net/community/forums/topic.asp?topic_id=410448

Share on other sites
kratz    134
Hey Captain thanks for your reply. That solution still doesn't work. If I remove the call to paintAll() I get a flicker of the inGamePanel. Does this mean that Swing repaints upon a call to setVisible(true)?

Share on other sites

Quote:
 1. Is it better to call addListener on everything or does an addListener on the parent JFrame automatically apply to all the visible child components?

Afaik, you need to add a listener to any component that you want to listen for events from that includes components within containers. Also if you notice in my example the JPanel no longer receives mouseMoved events when you are scrolling over one of the buttons.

Quote:
 2. I read somewhere that in 1.5 that adding to the contentPane is now the same thing as just adding to the parent frame. Is this true or is there an advantage to using getContentPane().add?
Well I did some research into the swing changes in 1.5 and here it is straight from the horses mouth. Of Course this only applies to 1.5 and will only work with the most recent jre. So to be compatible with earlier version of Java I would refrain from using JFrame.add(); and use JFrame.getContentPane().add(). The main reason behind using the getContentPane() was that swing was built on top of java.awt and JFrame was made a subclass of Frame. So I guess they needed a special Panel or something and they used that as the root which voided the Frame.add() function which actually is a convenience function for addImpl(). That method is now shown in the javax.swing.JFrame javadoc as being overridden and uses the ContentPane instead of using the java.awt.Frame implementation of the method which uses java.awt.Frame's built in pane.

Just a word of caution if you use the JFrame.add() function it will compile in earlier version of Java but you will get a runtime error telling you to use the getContentPane(). So if you are compiling for compatibility with older versions of java its better to use getContentPane().add().

Quote:
 I'm still working on the in-game menu without much success at all. I'm addin the panel like this in my setupGUI function...then I show the panel in my renderPaused function like this...well it erases my whole scene THEN shows the panel which is obviously not what I want. I guess I'm just having a hard time understanding how Swing paints things.Any suggestions?

I would suggest trying a different approach to in-game menus. Instead of worrying about displaying a panel on top of the current game frame you could create a undecorated JFrame window or subclass JDialog to create a modal dialog box which won't allow the user to change anything until they close the dialog window as long as you set the parent to the JDialog to be the games JFrame there is also a constructor to deal with a different GraphicsConfiguration but I don't know if that is needed. Though it might be for a fullscreen app.

You probably wouldn't have to change much code at all.

Hope that helps.

Share on other sites
kratz    134
5Minute thanks for the insights and the suggestion. I think I will give subclassing a JDialog a try and see if I get better results.

Thanks
Kratz

Share on other sites
Quote:
 Original post by kratz5Minute thanks for the insights and the suggestion. I think I will give subclassing a JDialog a try and see if I get better results. ThanksKratz

Anytime Kratz and please let us know how things work out.

Share on other sites
kratz    134
this is giving me such a headache. Either I'm just a piss-poor programmer or Swing is a convoluted pile of crap.

I decided to try working with a customized JDialog as an in-game menu but I can't even get this to work.

Remembering that I'm in fullscreen exclusive mode, I set up my dialog like this

inGamePanel = new JDialog(this);inGamePanel.setVisible(false);inGamePanel.setLayout(layout);inGamePanel.setIgnoreRepaint(true);inGamePanel.setBackground(Color.BLACK);inGamePanel.setPreferredSize(new Dimension(100, 200));		inGamePanel.setSize(inGamePanel.getPreferredSize());inGamePanel.setUndecorated(true);inGamePanel.setResizable(false);		inGamePanel.setLocation((width-inGamePanel.getWidth())/2,							(height-inGamePanel.getHeight())/2);inGamePanel.add(quitButton);inGamePanel.add(resumeButton);

and here is my continuous loop
while(running){    (Graphics2D)strategy.getDrawGraphics();if(manager.isPaused()){   renderPaused(myGraphics);   while(manager.isPaused())   	Thread.yield();			   continue;}//End if             //Update sprites   //Do regular rendering }//End While

Here is the check for Esc key to pause game and show the dialog
this of course is in the keyPressed sub

 //Check for ESC key to pull up inGameMenu if(e.getKeyCode() == e.VK_ESCAPE) {     manager.pause();     inGamePanel.setVisible(true);}//End if

and lastly here is the entire code for my renderPaused sub

private void renderPaused(Graphics2D g){   // clear offscreen canvas   g.setColor(Color.black);   g.fillRect(0, 0, width, HUD_HEIGHT);   g.drawImage(background, 0, HUD_HEIGHT, width, height, null);    g.setColor(Color.BLUE);   g.setFont(scoreFont);   g.drawString("PAUSED", width/2-75, height/2);   inGamePanel.paint(inGamePanel.getGraphics());   g.dispose();   strategy.show();}//End renderPaused

well all of this ALMOST works except when I press escape, the game pauses correctly but the dialog buttons don't show until I wave the mouse over them.

Kratz

Share on other sites
Hi Kratz,

I used a tutorial I am working on for an RTS game and added in a JDialog InGame menu. At first I was having the same problem you were with the buttons not showing. But then I looked a little closer and I found the problem. I was using java.awt.Components in a JDialog box. I then switched my buttons from java.awt.Button to javax.swing.JButton and everything worked fine.

Here is my code for the JDialog box.
import javax.swing.border.*;import java.awt.*;import javax.swing.*;import java.awt.event.*;public class InGameDialog extends JDialog {			private SimpleRTS myParent = null;		public InGameDialog( SimpleRTS parent, boolean modal ) {		super(parent,modal);		myParent = parent;		setUndecorated(true);		setIgnoreRepaint(false);//		setAlwaysOnTop(true);				setSize(400,300);				//center this dialog in the middle of the parent frame		int width = parent.getWidth();		int height = parent.getHeight();		Point screenCenter = new Point(width/2,height/2);		setLocationRelativeTo(parent);		setLocation( new Point( (int)(screenCenter.getX()-getWidth()/2), (int)(screenCenter.getY()-getHeight()/2)  ) );				JButton q = new JButton("Quit");		q.addActionListener( 			new ActionListener() {				public void actionPerformed( ActionEvent e ) {					setVisible(false);					dispose();					myParent.cleanup();					System.exit(0);				}			}		);				JButton s = new JButton("Save");		s.addActionListener(			new ActionListener() {				public void actionPerformed( ActionEvent e ) {									}				}		);				JButton l = new JButton("Load");		l.addActionListener(			new ActionListener() {				public void actionPerformed( ActionEvent e ) {									}				}		);				JButton o = new JButton("Options");		o.addActionListener(			new ActionListener() {				public void actionPerformed( ActionEvent e ) {									}				}		);		JButton r = new JButton("Resume");		r.addActionListener(			new ActionListener() {				public void actionPerformed( ActionEvent e ) {					setVisible(false);					dispose();				}				}		);				JPanel mid = new JPanel();		mid.setBorder( new EmptyBorder(20,50,20,50) );		mid.setLayout( new GridLayout(6,1) );		mid.add( s );		mid.add( l );		mid.add( o );		mid.add( q );		mid.add( new JSeparator() );		mid.add( r );				getContentPane().setLayout( new BorderLayout() );		getContentPane().add( "Center", mid );				setVisible(true);	}		}
SimpleRTS is a subclass of JFrame and has its own rendering method. To show the dialog box just use the following line in your main frame:

new InGameDialog( this, true );

Just make sure that you are using ALL SWING COMPONENTS. It's very bad to mix swing and awt. I hope that this can solve the problem your having and also help avoid further problems.

Share on other sites
kratz    134
Hey 5Minute thanks for the reply. You've been a big help. I think I got it mostly straightened out now. There were several things I was doing wrong. I thought that using setignoreRepaint(true) meant that I had to explicitly call some sort of paint function on my panel when I wanted to show it. So I was trying to paint using a Graphics2D object that I got from my main JFrame which was apparently causing strange behavior. All of this in addition to the fact that I was trying to paoint in the wrong places. Anyways, on to the next brick wall. Again thanks a million for your help.

Kratz