Problemas com exibição de gráficos

Tirei este programa do livro Use a Cabeça Java, quando executo aparecem somente um botão do lado direito e outro na parte inferior da janela, mas não aparece o circulo que, segundo o livro deveria aparecer.
Alguém sabe explicar o porquê?


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class SimpleGui3C implements ActionListener {
	
	JFrame frame;
	
	public static void main (String[] args) {
		SimpleGui3C gui = new SimpleGui3C();
		gui.go();
	}
	
	public void go() {
		frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JButton button = new JButton("Change colors");
		JButton button01 = new JButton("novo");
		
		button.addActionListener(this);
		
		MyDrawPanel drawPanel = new MyDrawPanel();
		
		frame.getContentPane().add(BorderLayout.SOUTH, button);
		frame.getContentPane().add(BorderLayout.EAST, button01);
		frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
		frame.setSize(300,300);
		frame.setVisible(true);
	}
	
	public void actionPerformed(ActionEvent event) {
		frame.repaint();
	}
}

	
class MyDrawPanel extends JPanel {
	public void paintComponet(Graphics g) {
		g.fillRect(0,0,this.getWidth(), this.getHeight());
		
		int red = (int) (Math.random() * 255);
		int green = (int) (Math.random() * 255);
		int blue = (int) (Math.random() * 255);
		
		Color randomColor = new Color(red,green,blue);
		g.setColor(randomColor);
		g.fillOval(70,70,100,100);
	}
}

Oi, formate o seu código usando a tag code:
http://www.guj.com.br/posts/list/50115.java

Você deve tirar uma cópia do objeto Graphics antes de usa-lo. Isso é muito importante e caso você não faça isso, pode gerar problemas sérios no visual da sua aplicação.

Para fazer isso é só deixar o seu método assim:

[code]
class MyDrawPanel extends JPanel {
public void paintComponet(Graphics graphics) {
Graphics2D g = (Graphics2D) graphics.create(); //Cria a cópia
g.fillRect(0,0,this.getWidth(), this.getHeight());

  int red = (int) (Math.random() * 255);
  int green = (int) (Math.random() * 255);
  int blue = (int) (Math.random() * 255);

  Color randomColor = new Color(red,green,blue);
  g.setColor(randomColor);
  g.fillOval(70,70,100,100);
  d.dispose(); //Libera a cópia.

}
} [/code]

Obrigado pela dica sobre a formatação, e desculpa aí… coisa de iniciante.

[code]
import javax.swing.;
import java.awt.
;
import java.awt.event.*;

public class SimpleGui3C implements ActionListener {

JFrame frame;

public static void main (String[] args) {
	SimpleGui3C gui = new SimpleGui3C();
	gui.go();
}

public void go() {
	frame = new JFrame();
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	JButton button = new JButton("Change colors");
	JButton button01 = new JButton("novo");
	
	button.addActionListener(this);
	
	MyDrawPanel drawPanel = new MyDrawPanel();
	
	frame.getContentPane().add(BorderLayout.SOUTH, button);
	frame.getContentPane().add(BorderLayout.EAST, button01);
	frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
	frame.setSize(300,300);
	frame.setVisible(true);
}

public void actionPerformed(ActionEvent event) {
	frame.repaint();
}

}

/*
class MyDrawPanel extends JPanel {
public void paintComponet(Graphics g) {
g.fillRect(0,0,this.getWidth(), this.getHeight());

	int red = (int) (Math.random() * 255);
	int green = (int) (Math.random() * 255);
	int blue = (int) (Math.random() * 255);
	
	Color randomColor = new Color(red,green,blue);
	g.setColor(randomColor);
	g.fillOval(70,70,100,100);
}

}
*/
class MyDrawPanel extends JPanel {
public void paintComponet(Graphics graphics) {
Graphics2D g = (Graphics2D) graphics.create(); //Cria a cópia
g.fillRect(0,0,this.getWidth(), this.getHeight());

   int red = (int) (Math.random() * 255);  
   int green = (int) (Math.random() * 255);  
   int blue = (int) (Math.random() * 255);  

   Color randomColor = new Color(red,green,blue);  
   g.setColor(randomColor);  
   g.fillOval(70,70,100,100);  
   g.dispose(); //Libera a cópia.  
}  

}[/code]

Não funcionou. A imagem fica assim.

Aquilo não ia funcionar mesmo. Era só uma boa prática do Swing. Mas não afeta o resultado final da pintura.
Eu não tinha olhado o resto do seu código porque estava sem formatação, e fica ruim de ler. Então, só vi o ponto onde quase todo mundo erra.

No seu actionPerformed tente fazer o seguinte:

public void actionPerformed(ActionEvent event) { drawPanel.revalidate(); frame.repaint(); }

Claro que para fazer isso você terá que guardar o drawPanel numa propriedade, e não simplesmente numa variável local.

Sem esse comando, o Swing identifica que não houve alterações nem no frame e nem no painel, e ignora solenemente o seu comando de repaint. Sem esse comando, vc pode tentar minimizar e maximizar sua janela. O painel deve mudar de cor do mesmo jeito (já que isso também causa um repaint() completo).

PS: Se quiser fazer um tutorial mais divertido que esse da Kathy, tente esse aqui:
http://www.cokeandcode.com/node/6

Ele é mais sobre Java2D do que Swing, mas o resultado é mais animador.

guardar o drawPanel numa propriedade?
Desculpe, pode explicar melhor?

Basta fazer como você fez com o frame:

[code]
public class SimpleGui3C implements ActionListener {

private JFrame frame;   
private MyDrawPanel drawPanel; //Aqui, uma propriedade.
//Resto do código aqui

}[/code]

Acho que o problema é o nome do teu método:

public void paintComponet(Graphics graphics)

deveria ser:

protected void paintComponent(Graphics g).

Fernando Rosa

Bem observado. Por isso é uma boa usar a tag @Override, sempre que sobrescrever um método.

Esse erro já teria sido pego de cara.

Fiz as modificações sugeridas, mas… continua não funcionando.
Alguém poderia executar este fonte e verificar se o resultado é o mesmo?

[code]
import javax.swing.;
import java.awt.
;
import java.awt.event.*;

public class SimpleGui3C implements ActionListener {

 private JFrame frame;  
 private MyDrawPanel drawPanel; 
    
 public static void main (String[] args) {  
     SimpleGui3C gui = new SimpleGui3C();  
     gui.go();  
 }  
   
 public void go() {  
     frame = new JFrame();  
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
     JButton button = new JButton("Change colors");  
     JButton button01 = new JButton("novo");  
       
     button.addActionListener(this);  
       
     drawPanel = new MyDrawPanel();  
       
     frame.getContentPane().add(BorderLayout.SOUTH, button);  
     frame.getContentPane().add(BorderLayout.EAST, button01);  
     frame.getContentPane().add(BorderLayout.CENTER, drawPanel);  
     frame.setSize(300,300);  
     frame.setVisible(true);  
 }  
   
 public void actionPerformed(ActionEvent event) {  
     drawPanel.revalidate();
     frame.repaint();  
 }  

}

class MyDrawPanel extends JPanel {
protected void paintComponet(Graphics graphics) {
Graphics2D g = (Graphics2D) graphics.create(); //Cria a cópia
g.fillRect(0,0,this.getWidth(), this.getHeight());

  int red = (int) (Math.random() * 255);  
  int green = (int) (Math.random() * 255);  
  int blue = (int) (Math.random() * 255);  

  Color randomColor = new Color(red,green,blue);  
  g.setColor(randomColor);  
  g.fillOval(70,70,100,100);  
  g.dispose(); //Libera a cópia.  

}
}[/code]

Nesse código que vc colou o seu paintComponent continua com nome errado.

Eu rodei aqui, só troquei o nome do método para o certo e funcionou de cara.

ViniGodoy, você poderia postar o código que funcionou?

Posso, mas qual a dificuldade de acrescentar uma letra “n” na palavra paintComponent?

[code] import javax.swing.;
import java.awt.
;
import java.awt.event.*;

public class SimpleGui3C implements ActionListener {

 private JFrame frame;  
 private MyDrawPanel drawPanel; 
    
 public static void main (String[] args) {  
     SimpleGui3C gui = new SimpleGui3C();  
     gui.go();  
 }  
   
 public void go() {  
     frame = new JFrame();  
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
     JButton button = new JButton("Change colors");  
     JButton button01 = new JButton("novo");  
       
     button.addActionListener(this);  
       
     drawPanel = new MyDrawPanel();  
       
     frame.getContentPane().add(BorderLayout.SOUTH, button);  
     frame.getContentPane().add(BorderLayout.EAST, button01);  
     frame.getContentPane().add(BorderLayout.CENTER, drawPanel);  
     frame.setSize(300,300);  
     frame.setVisible(true);  
 }  
   
 public void actionPerformed(ActionEvent event) {  
     drawPanel.revalidate();
     frame.repaint();  
 }  

}

class MyDrawPanel extends JPanel {
@Override
protected void paintComponent(Graphics graphics) {
Graphics2D g = (Graphics2D) graphics.create(); //Cria a cópia
g.fillRect(0,0,this.getWidth(), this.getHeight());

  int red = (int) (Math.random() * 255);  
  int green = (int) (Math.random() * 255);  
  int blue = (int) (Math.random() * 255);  

  Color randomColor = new Color(red,green,blue);  
  g.setColor(randomColor);  
  g.fillOval(70,70,100,100);  
  g.dispose(); //Libera a cópia.  

}
}[/code]

Você negritou e eu nem percebi :shock: , foi mal, desculpa aí.
Eu fiz essa modificação na versão original e funcionou de cara. O pior é que, na versão com erro, compilou beleza, só não dava o resultado esperado.
De qualquer forma eu fico muito agradecido pela ajuda! Valeu, um abraço! :smiley:

[quote=fredericodossantos]Você negritou e eu nem percebi :shock: , foi mal, desculpa aí.
Eu fiz essa modificação na versão original e funcionou de cara. O pior é que, na versão com erro, compilou beleza, só não dava o resultado esperado.
De qualquer forma eu fico muito agradecido pela ajuda! Valeu, um abraço! :smiley: [/quote]

Compilou porque foi criado um novo método para a classe MyDrawPanel cujo nome era paintComponet que nunca era chamado, ao invés de se sobrepor ao método paintComponent da classe JPanel a qual MyDrawPanel extende. Estou certo?

Está certo. Por isso é importante usar o @Override sempre que vc estender uma classe e reimplementar um método. Assim o compilador consegue saber de sua intenção (que é a de sobrescrever alguma coisa) e pode te avisar que o método em questão não está sobrescrevendo nada. É especialmente útil se vc mudar o nome do método na classe pai (aí o compilador não deixa vc esquecer de mudar também na classe filha).

Só tem uma coisa errada. Embora a palavra extensão seja mesmo com “x” a palavra estender é com “s”.

Isso porque a palavra estender vem do latim vulgar e a palavra extensão do latim clássico.
E porque o português não seria o português sem pegadinhas como essa… :wink:

Valeu, eu nem percebi que havia escrito com “X” agora que você fez a observação e eu reli a mensagem foi que notei, fica extranho :stuck_out_tongue: mesmo. Muito Obrigado, novamente!

Acho que é pq no Java a gente “extends” muito. :lol: