Ajuda com frame panel e label e métodos paint/paintComponent

olá a todos!
sou nova no java e estou bastante confusa no momento. sei que minha duvida é corriqueira, mas ja procuro há algum tempo e ainda não encontrei algo que solucionasse meu problema.

a situação é a seguinte:

tenho um jframe, uso o getContentPane e armazeno em um container.
depois crio um JPanel com uma imagem que será o fundo e adiciono ao container com uma mensagem de “Pressione qualquer tecla para continuar”.
Quando a tecla é pressionada, deve ser disparada uma chamada de função que mostra um menu. Até aí tudo bem, os problemas começam na hora de mostrar o menu.

Possuo uma classe Menu que extende JPanel. Esta classe possui 3 atributos que são Classes diferenciadas, mas todas extendem MenuOpt que extende JLabel. (Sei que ficou um pouco confuso, se depois de tudo houver um modo mais simples de fazer isso, por favor me avise!!!)

Cada MenuOpt possui coordenadas x e y, e um Sprite. A classe Sprite possui apenas uma Image e alguns métodos, dentre eles um método draw(Graphics g), que faz só um g.drawImage e desenha o sprite.

fiz o seguinte:
criei o Menu usando o construtor. Este construtor chama os construtores das tres opções do menu e as armazena.Depois as adiciona ao Menu usando add(opção de menu)
logo após usei container.add(menu) em outro lugar, para adicionar o menu.

Então sobrescrevi o método paintComponent do Menu para fazer opção de menu1.repaint(), etc
e sobrescrevi o método paintComponent de MenuOpt para fazer sprite.draw(g,x,y)

no entanto, nada acontece.

No final, o que quero é mostrar o menu por cima da imagem de fundo, sendo que cada imagem seria uma label e o menu um panel.

Alguém pode me dar uma luz? Se necessário posso colocar um trecho do código, é só pedir. E desculpem se me extendi, mas achei que não ficaria claro se explicasse menos…
Aguardo

Bom, poste suas classes Menu e MenuOpt.

Use para isso a tag code, como descrito aqui:
http://www.guj.com.br/posts/list/50115.java

Desculpe a demora :oops:
MenuOpt é como segue:

[code]
/**

  • Represents an option of the start Menu
  • @author Maitê Friedrich Dupont

/
public class MenuOpt extends JLabel{
/
* The picture of the option /
private Sprite feather;
/
* The x coordinate where to put this option /
int x;
/
* The y coordinate where to put this option /
int y;
/
* True if the mouse clicked this option */
boolean buttonClicked;

/** Initializes the option. Adds listener to sense mouse actions. */
MenuOpt(String ref, int x, int y){
	this.feather = SpriteStore.get().getSprite(ref);
	this.x = x;
	this.y = y;
	
	addMouseListener(new MouseListener()
    {
        public void mouseClicked (MouseEvent e){}
        public void mouseEntered (MouseEvent e){}
        public void mouseExited (MouseEvent e){}
        public void mousePressed (MouseEvent e){}
        public void mouseReleased (MouseEvent e){
        	doAction();
        }
    });//end Mouse action 
}
/** Implements what the button is supposed to do when clicked 
 * 
 */
private void doAction() {
	
}
public MenuOpt get(){
	return this;
}

public void draw(Graphics g) {
	feather.draw(g, x, y);

}
public void paintComponent(Graphics g){
	feather.draw(g, x, y);
	
}

}[/code]

E Menu é assim:


/** This class represents the initial menu of the game, with its 
 * three options :
 * 	New Game	 -  to start a new Game, because Killing chickens IS fun.
 * 	High Score	 -  to view the names of the ones with the best scores
 *  Credits		 -  to view the names of all the 
 *  		people who participated in the creation of this game
 * @author Maitê
 *
 */
public class Menu extends JPanel {
	private StartOpt startNewGame;
	private CreditsOpt viewCredits;
	private HighOpt viewHighScore;
	
	Menu(JPanel menuPanel){
		
		startNewGame = new StartOpt("sprites/featherNG.gif",215,26);
		add(startNewGame);

		viewHighScore = new HighOpt("sprites/featherH.gif",215,177);
		add(viewHighScore);

		viewCredits = new CreditsOpt("sprites/featherC.gif",215,328);
		add(viewCredits);
	}

	/** Returns the menu option Start New Game 
	 * 
	 */
	
	public MenuOpt getStart(){
		return startNewGame.get();
	}
	/** Returns the menu option View High Score
	 * 
	 */
	public MenuOpt getHigh(){
		return viewHighScore.get();
	}
	/** Returns the menu option View Credits 
	 * 
	 */
	public MenuOpt getCred(){
		return viewCredits.get();
	}
	
}

Bem, se você está fazendo um game, é uma péssima idéia fazer misturando componentes do Swing. O ideal seria você usar o Java 2D direto (no meu site, o ponto v, tem tutoriais à respeito).

Bom, pode postar também a classe Sprite e o local onde você cria esses menus?

sim, estou fazendo um game. é um projeto para a faculdade. acontece que estou muito confusa sobre este tipo de componente, quando se usa label, panel, frame, ou graphics 2d???


import java.awt.Graphics;
import java.awt.Image;

/**
 * A sprite to be displayed on the screen. Note that a sprite
 * contains no state information, i.e. its just the image and 
 * not the location. This allows us to use a single sprite in
 * lots of different places without having to store multiple 
 * copies of the image.
 * 
 * @author Kevin Glass
 */

esta é a classe sprite, que eu estou reutilizando. junto com ela vem a classe spritestore

public class Sprite {
	/** The image to be drawn for this sprite */
	private Image image;
	
	/**
	 * Create a new sprite based on an image
	 * 
	 * @param image The image that is this sprite
	 */
	public Sprite(Image image) {
		this.image = image;
	}
	
	/**
	 * Get the width of the drawn sprite
	 * 
	 * @return The width in pixels of this sprite
	 */
	public int getWidth() {
		return image.getWidth(null);
	}

	/**
	 * Get the height of the drawn sprite
	 * 
	 * @return The height in pixels of this sprite
	 */
	public int getHeight() {
		return image.getHeight(null);
	}
	
	/**
	 * Draw the sprite onto the graphics context provided
	 * 
	 * @param g The graphics context on which to draw the sprite
	 * @param x The x location at which to draw the sprite
	 * @param y The y location at which to draw the sprite
	 */
	public void draw(Graphics g,int x,int y) {
		g.drawImage(image,x,y,null);
	}
}

e spritestore:


import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;

import javax.imageio.ImageIO;

/**
 * A resource manager for sprites in the game. Its often quite important
 * how and where you get your game resources from. In most cases
 * it makes sense to have a central resource loader that goes away, gets
 * your resources and caches them for future use.
 * <p>
 * [singleton]
 * <p>
 * @author Kevin Glass
 */
public class SpriteStore {
	/** The single instance of this class */
	private static SpriteStore single = new SpriteStore();
	
	/**
	 * Get the single instance of this class 
	 * 
	 * @return The single instance of this class
	 */
	public static SpriteStore get() {
		return single;
	}
	
	/** The cached sprite map, from reference to sprite instance */
	private HashMap sprites = new HashMap();
	
	/**
	 * Retrieve a sprite from the store
	 * 
	 * @param ref The reference to the image to use for the sprite
	 * @return A sprite instance containing an accelerate image of the request reference
	 */
	public Sprite getSprite(String ref) {
		// if we've already got the sprite in the cache
		// then just return the existing version
		if (sprites.get(ref) != null) {
			return (Sprite) sprites.get(ref);
		}
		
		// otherwise, go away and grab the sprite from the resource
		// loader
		BufferedImage sourceImage = null;
		
		try {
			// The ClassLoader.getResource() ensures we get the sprite
			// from the appropriate place, this helps with deploying the game
			// with things like webstart. You could equally do a file look
			// up here.
			URL url = this.getClass().getClassLoader().getResource(ref);
			
			if (url == null) {
				fail("Can't find ref: "+ref);
			}
			
			// use ImageIO to read the image in
			sourceImage = ImageIO.read(url);
		} catch (IOException e) {
			fail("Failed to load: "+ref);
		}
		
		// create an accelerated image of the right size to store our sprite in
		GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
		Image image = gc.createCompatibleImage(sourceImage.getWidth(),sourceImage.getHeight(),Transparency.BITMASK);
		
		// draw our source image into the accelerated image
		image.getGraphics().drawImage(sourceImage,0,0,null);
		
		// create a sprite, add it the cache then return it
		Sprite sprite = new Sprite(image);
		sprites.put(ref,sprite);
		
		return sprite;
	}
	
	/**
	 * Utility method to handle resource loading failure
	 * 
	 * @param message The message to display on failure
	 */
	private void fail(String message) {
		// we're pretty dramatic here, if a resource isn't available
		// we dump the message and exit the game
		System.err.println(message);
		System.exit(0);
	}
}

Para games, você não usa nenhum componente do Swing, tudo é feito usando o Graphics2D. E o controle é feito inteiramente por você.
É que o swing tem um ciclo específico de pintura. E esse ciclo não vai bater com o game loop.

Você já deu uma lida nos tutoriais de Java 2D do Ponto V?

ainda não, só terei tempo à noite.
mas dei uma olhada e parece que tem muita informação que será útil =]
mas essa parte do jogo é só o menu inicial, tipo onde o usuário escolhe se quer começar um novo jogo etc, imaginei que poderia fazer com swing, já que não é o jogo propriamente dito, e não tem maiores animações a não ser a tecla a ser pressionada para exibir o menu e o clique do usuário na opção desejada.

Até pode. Mas esqueça recursos mais interessantes que os menus de jogos tem, como sons, animações ao selecionar o menu com o mouse, troca de fontes, etc. Tudo isso fica pouco prático de se fazer.

Se quiser, uma maneira fácil é usar JImagePanels: http://www.guj.com.br/posts/list/56248.java#295271

Mesmo para botões. Seu menu seria só um conjunto de sobreposições de painéis.

E vai ser um jogo de que?

bem, não sei dizer ao certo de que seria… falando de estilo, mas é assim:
você controla um carro e o objetivo é matar as galinhas que tentam atravessar a rua desviando dos ovos que elas põe…
:stuck_out_tongue:
vou ler os tutoriais que você falou e pesquisar mais sobre essa classe.

demorei, mas finalmente consegui! Muito obrigada pelas sugestões e pelos artigos, ajudaram muito!!
Agora estou com problemas na integração do menu com o jogo, será que dá pra resolver aqui mesmo?

jogo em si está pronto,e agora fiz um menu inicial para ele mas na hora de integrar, o jogo não funciona.
Inicialmente fiz o menu em um JFrame e o jogo em outro, e quando o usuário apertasse Start Game o Frame do jogo apareceria e o do menu desapareceria. Até aí tudo bem, mas o jogo fica descentralizado no frame novo, e não responde aos comandos do teclado nem nada. Até o X para fechar para de funcionar. Tenho que fechar o programa pelo gerenciador de tarefas…

Então tentei fazer tudo em um frame só e o problema da descentralização diminuiu, mas não foi resolvido, e o jogo continua sem responder…

aqui estão os códigos que criam os frames:

cria a tela com o menu

[code]Initial(){

	setTitle("Chicken Killer");
	setSize(new Dimension(800,600));
	setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	back = SpriteStore.get().getSprite("sprites/front.jpg");
	menuShown = false;
	
	addKeyListener(new KeyListener() {
		public void keyTyped(KeyEvent e) {}
		public void keyPressed(KeyEvent e) {
			if (menuShown){
				if (e.getKeyCode() == KeyEvent.VK_UP) {
					menu.selectPreviousOption();
					paintScreen();
				}
				if (e.getKeyCode() == KeyEvent.VK_DOWN) {
					menu.selectNextOption();
					paintScreen();
				}
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					enterPressed();
				}
			}
			else {
				menu = new Menu();
				menuShown = true;
				paintScreen();
			}
		}[/code]

cria a tela do jogo

[code]public Game(Initial menuScreen) {
menuScreen.dispose();
// create a frame to contain our game
JFrame container = new JFrame(“ChickenKiller”);

	// get hold the content of the frame and set up the resolution of the game
	JPanel panel = (JPanel) container.getContentPane();
	panel.setPreferredSize(new Dimension(800,600));
	panel.setLayout(null);
	
	// setup canvas size and put it into the content of the frame
	setBounds(0,0,800,600);
	panel.add(this);
	
	// Tell AWT not to bother repainting our canvas since we're
	// going to do that our self in accelerated mode
	setIgnoreRepaint(true);
	
	// make the window visible 
	container.pack();
	container.setResizable(false);
	container.setVisible(true);
	
	// add a listener to respond to the user closing the window. 
	container.addWindowListener(new WindowAdapter() {
		public void windowClosing(WindowEvent e) {
			System.exit(0);
		}
	});
	
	// add a key input system (defined below) to canvas
	// so it can respond to key pressed
	addKeyListener(new KeyInputHandler());
	
	// request the focus so key events come to us
	requestFocus();

	// create the buffering strategy which will allow AWT
	// to manage the accelerated graphics
	createBufferStrategy(2);
	strategy = getBufferStrategy();
	
	//initializes the game entities
	initEntities();
}[/code]