Erro no Desenho

8 respostas
lordtiago

Galera sou iniciante e estou apanhando pra caramba,
tava criando este código aqui, uso o JDK 1.6 mas a tela branca para desenho não aparece, ela fica transparente.

Se alguem puder me explicar o que está acontecendo, ficaria grato
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Desenho extends JFrame{
	int posX = -10, posY = -10;
	
	public Desenho () {
		super ("Quase o Java Paint que tava tentando criar, rs");
	
	addMouseMotionListener (new MouseMotionAdapter (){
			public void mouseDragged (MouseEvent e) {
				posX = e.getX();
				posY = e.getY();
				setBackground (Color.red);
				repaint ();
				
			}
		}
	);
	setBackground (Color.white);
	setSize (300, 250);
	
	setVisible (true);
	repaint ();
}
public static void main (String args []){
	Desenho app = new Desenho ();
	app.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
}
public void paint (Graphics g){
	g.fillRect (posX, posY, 5, 5);
}
}
Desde já valeu!

8 Respostas

T

a) Você não pode sobreescrever o método “paint”, só “paintComponent”.
b) Em vez de sobreescrever o método do próprio JFrame, crie uma classe derivada de JPanel e sobreescreva o método “paintComponent”.

T

Exemplo do que disse. (Este programa tem um problema. O que ocorre se você redimensionar o frame, ou minimizá-lo e restaurá-lo?)

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

class MeuCanvas extends JPanel {

    private int x1, x2, y1, y2;
    private Color color;
    
    public void setCoords (int pX1, int pY1, int pX2, int pY2) {
        x1 = pX1; y1 = pY1; x2 = pX2; y2 = pY2;
    }
    
    public void setColor (Color pColor) {
        color = pColor;
    }
    
    /**
     * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
     */
    protected void paintComponent(Graphics pG) {
        Graphics2D g2d = (Graphics2D) pG.create();
        g2d.setPaint(color);
        g2d.fillOval(x1, y1, x2 - x1, y2 - y1);
        g2d.dispose();
    }
}

/**
 */
public class TesteDesenho extends JFrame {

    private static final long serialVersionUID = 1L;

    private MeuCanvas meuCanvas = null;

    /**
     * This is the default constructor
     */
    public TesteDesenho() {
        super();
        initialize();
    }

    /**
     * This method initializes this
     * 
     * @return void
     */
    private void initialize() {
        this.setSize(300, 200);
        this.setContentPane(getMeuCanvas());
        this.setTitle("Teste de Desenho");
    }

    /**
     * This method initializes meuCanvas
     * 
     * @return javax.swing.JPanel
     */
    private JPanel getMeuCanvas() {
        if (meuCanvas == null) {
            meuCanvas = new MeuCanvas();
            meuCanvas.addMouseMotionListener(new MouseMotionAdapter() {

                /**
                 * @see java.awt.event.MouseMotionAdapter#mouseDragged(java.awt.event.MouseEvent)
                 */
                public void mouseDragged(MouseEvent pE) {
                    int x1 = pE.getX(); int y1 = pE.getY();
                    int x2 = x1 + 10; int y2 = y1 + 10;
                    meuCanvas.setCoords(x1, y1, x2, y2);
                    meuCanvas.setColor (Color.RED);
                    repaint();
                }
                
            });
        }
        return meuCanvas;
    }

    public static void main(String[] args) {
        TesteDesenho td = new TesteDesenho();
        td.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        td.setVisible(true);
    }
}
davidbuzatto

Algumas observações:

[list]A classe JFrame não tem o método paintComponent, sendo assim vc está correto em sobrescrever o método paint.[/list]
[list]O método paintComponent existe a partir das classes derivadas de JComponent. Sendo assim, quando uma classe for subclasse de JComponent, ai sim vc vai sobrescrever o paintComponent.[/list]
[list]Sempre quando sobrescrever o paint ou paintComponent, SEMPRE chame a versão do método da superclasse para garantir que o componente seja pintado da forma correta.[/list]

Por exemplo:

public class MeuPainel extends JPanel { protected void paintComponent( Graphics g ) { super.paintComponent( g ); // aqui vem o que vc quer fazer... } }

Seu código não estava funcionando por causa disso :smiley:

[list]Cuidado ao trabalhar com os JFrames, pois a barra de título também é considerada como parte do JFrame.[/list]

Altere o seu método paint para o seguinte.

public void paint( Graphics g ) { super.paint( g ); g.fillRect( 0, 0, 50, 50 ); }

Note que será desenhado um retângulo a partir do canto superior esquerdo da janela, e não a partir da barra de título.

Como o thingol falou, é mais interessante criar uma subclasse de JPanel e depois adicionar no JFrame.

Abraço!

lordtiago

Testei as dicas postadas, e observei uma coisa.
No primeiro código que postei, quando eu redimensiono a janela, ou altero seu tamanho, a tela de trás dos outros aplicativos que fora copiada (dando a impressão de estar transparente), some. Daí sim é possivel desenhar. E se for novamente redimensionada, a ocorrência do recorte na imagem.

O resultado final foi esse:

[url]http://rpg-animes.50webs.com/teste.jpg[/url]

Só que como faço pra ele não copiar o fundo quando carrega e eu não ter q redimensionar a janela.

David, quanto ao Frame, que conta a medida da barra de título, há alguma apostilinha ou guia que possa me ensinar a explorar o JFrame de modo que minha tela não comece com a barra de título?

E quanto às dicas dadas eu agradeço, mas seguindo-as apareceu outro problema, o desenho não sai, mas sim um ponto que é apagado automáticamente e redesenhado, seguindo o cursor até eu parar. No caso, o resultado final esperado era um pincel, como aqueles do paint.

O novo código seguindo a dica que vocês me deram ficou assim:

import java.awt.event.MouseEvent;   
import java.awt.event.MouseMotionAdapter;

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

public class Desenho extends JPanel{
	int posX = -10, posY = -10;
	
	public void setCoords (int pX1, int pY1){
		posX= pX1; posY = pY1;
	}
	
	protected void paintComponent(Graphics g) {  
		super.paintComponent( g );    
        
        g.fillRect (posX, posY, 5, 5);
	}
}


 class TesteDesenho extends JFrame {
	Desenho desenho = new Desenho();
	public TesteDesenho() {   
        super();   
        initialize();   
    } 
    
    private void initialize() {   
        this.setSize(800, 600);   
        this.setContentPane(folhaDesenho());   
        this.setTitle("Quase o Java Paint que tava tentando criar, rs");   
        
        this.setVisible(true);
    }   

	
	private JPanel folhaDesenho() {   
        
               
            desenho.addMouseMotionListener(new MouseMotionAdapter() {   
  
                /**  
                 * @see java.awt.event.MouseMotionAdapter#mouseDragged(java.awt.event.MouseEvent)  
                 */   
                public void mouseDragged(MouseEvent pE) {   
                     int x1= pE.getX();
	     int y1= pE.getY(); 
	    desenho.setCoords(x1, y1);
                    repaint();   
                }   
                   
            });   
             return desenho;  
        }   
        	

public static void main (String args []){
	
	TesteDesenho td = new TesteDesenho();   
        td.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);   
        td.setVisible(true); 
}

}

Eu tô apanhando com programação, mas aos poucos eu vô apredendo.

T

Você rodou o meu programa? Ele faz o que você quer (desenhar como se fosse o Paint).

Basicamente o que o Buzatto não disse, porque você não explicou o que queria, é que você precisa armazenar em alguma estrutura sua da memória as posições do cursor para que você possa refazer o desenho no evento paintComponent.

Vou mexer no meu exemplo para que fique conforme o que o Buzatto disse:

T
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.List;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

class MeuCanvas extends JPanel {

    private int x1, x2, y1, y2;
    private Color color;
    // Lista dos pontos a serem desenhados
    private List<Point> points = new ArrayList<Point>();
    
    public void addNewPoint (int pX, int pY) {
        points.add (new Point (pX, pY));
    }
    
    public void clearPoints() {
        points.clear();
    }
    
    public void setColor (Color pColor) {
        color = pColor;
    }
    
    /**
     * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
     */
    protected void paintComponent(Graphics pG) {
        super.paintComponent(pG);
        Graphics2D g2d = (Graphics2D) pG.create();
        g2d.setPaint(color);
        for (Point point : points) {
            g2d.fillOval(point.x - 5, point.y - 5, 10, 10);
        }
        g2d.dispose();
    }
}

/**
 */
public class TesteDesenho extends JFrame {

    private static final long serialVersionUID = 1L;

    private MeuCanvas meuCanvas = null;

    /**
     * This is the default constructor
     */
    public TesteDesenho() {
        super();
        initialize();
    }

    /**
     * This method initializes this
     * 
     * @return void
     */
    private void initialize() {
        this.setSize(300, 200);
        this.setContentPane(getMeuCanvas());
        this.setTitle("Teste de Desenho");
    }

    /**
     * This method initializes meuCanvas
     * 
     * @return javax.swing.JPanel
     */
    private JPanel getMeuCanvas() {
        if (meuCanvas == null) {
            meuCanvas = new MeuCanvas();
            meuCanvas.addMouseMotionListener(new MouseMotionAdapter() {

                /**
                 * @see java.awt.event.MouseMotionAdapter#mouseDragged(java.awt.event.MouseEvent)
                 */
                public void mouseDragged(MouseEvent pE) {
                    int x1 = pE.getX(); int y1 = pE.getY();
                    meuCanvas.addNewPoint (x1, y1);
                    meuCanvas.setColor (Color.RED);
                    repaint();
                }
                
            });
        }
        return meuCanvas;
    }

    public static void main(String[] args) {
        TesteDesenho td = new TesteDesenho();
        td.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        td.setVisible(true);
    }
}
ViniGodoy

Para explorar o JFrame, dê uma olhada no método getInsets(). É esse cara que vai te dar as medidas das bordas do JFrame, e isso inclui a barra de títulos.

Mas, se você só quer pintar dentro do JFrame, eu também faria como Thingol recomendou: usando um JPanel. Assim, você não só não precisa se preocupar com os insets, como também ainda ganha a flexibilidade de poder usar esse painel em apenas uma parte do frame, usa-lo em conjunto com o JScrollPane para ter barras de rolagem ou coloca-lo de maneira integrada aos outros componentes: embaixo de uma barra de ferramentas ou num SplitPane, por exemplo.

Se for fazer um jogo que ocupe a tela toda, como o caso do JMario do David ou do meu Vikanoid, aí sim, sobrescreva o JFrame todo e ainda de quebra use o método setDecorated(false) para tirar toda e qualquer borda que ele possa ter. Mas no caso de um Paint ou um editor vetorial, é melhor ficar no JPanel mesmo.

lordtiago

agora entendi o lance do panel e paint component.
Bom obrigado pelas dicas.

Criado 9 de outubro de 2007
Ultima resposta 12 de out. de 2007
Respostas 8
Participantes 4