[java] hideable panel

Started by
10 comments, last by kratz 17 years, 7 months ago
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
---------------------------Noobies have feelings too!!----------------------------
Advertisement
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!
“every idea is a responsibility”
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.
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
---------------------------Noobies have feelings too!!----------------------------
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?
Thanks
kratz


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

Call paint(g), instead of paintAll(g).
"None of us learn in a vacuum; we all stand on the shoulders of giants such as Wirth and Knuth and thousands of others. Lend your shoulders to building the future!" - Michael Abrash[JavaGaming.org][The Java Tutorial][Slick][LWJGL][LWJGL Tutorials for NeHe][LWJGL Wiki][jMonkey Engine]
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)?
---------------------------Noobies have feelings too!!----------------------------
Hi kratz your welcome, glad to help

regarding your questions:

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.
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
---------------------------Noobies have feelings too!!----------------------------
Quote:Original post by kratz
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

Anytime Kratz and please let us know how things work out.
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.

Someone please save me cause I'm ready to smash something.

Kratz
---------------------------Noobies have feelings too!!----------------------------

This topic is closed to new replies.

Advertisement