Método Paint da classe Japplet

Estou com um problema novo…

Eu tenho uma malha de pontos e preciso que o ponto apontado pelo mouse seja destacado, e preciso que isso seja dinâmico, tentei fazer um código pra isso, acho que cheguei perto, mas o “destaque” do ponto não some, fica lá e se eu passar por 10 pontos os 10 ficarão destacados Y_Y

[code]import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JApplet;

public class NewJApplet extends JApplet {
Point malha[][];
Point area;
Point foco;

int k;
int l;

@Override
public void init() {
    area = new Point();
    foco = new Point(-1, -1);
    carregaMalha(10);
    addMouseMotionListener(new MouseAdapter() {
        @Override
        public void mouseMoved(MouseEvent e) {
            foco.setLocation(-1, -1);
            for (int i = 0; i < k; i++)
                if (e.getX() == malha[i][0].x){
                    for (int j = 0; j < l; j++)
                        if (e.getY() == malha[i][j].y){
                            foco.setLocation(e.getX(), e.getY());
                        } 
                }
            repaint();  
        }
    });
    
}

@Override
public void paint(Graphics g){
    for (int i = 0; i <k; i++){
        for (int j = 0; j < l; j++){
            g.drawOval((malha[i][j].x -1), (malha[i][j].y -1), 1, 1);
        }
    }
    if (foco.x > 0){
        g.setColor(Color.red);
        g.drawRect((foco.x -2), (foco.y -2), 4, 4);
        g.setColor(Color.black);
    }
}

private void carregaMalha(int passo){
            
    area.x = this.getWidth();
    area.y = this.getHeight();
   
    k = area.x/passo;
    l = area.y/passo;

    malha = new Point[k][l];
    for (int i=0; i<k; i++){
        for (int j=0; j<l; j++){
            malha[i][j] = new Point(i*passo, j*passo);
        }
    }

}

}[/code]

alguem sabe porquê isso ocorre?

  1. Você deve sobrescrever o método paintComponent, não o paint;
  2. Você deve fazer uma cópia do objeto Graphics, antes de aplicar a pintura (o estado dele não pode ser alterado);
  3. Você deve limpar a área de desenho, antes de pintar os pontos. Como vc traça um quadrado ao redor do ponto destacado, não há nada que apague o quadrado antigo, durante a repintura.

Para limpar a área de pintura, use o método fillRect com a cor do fundo. Dá uma lida no material de Java2D que está no meu site, acho que você vai gostar.

Ah, e por favor, dúvidas no fórum, ok? não via MP. Aí todos podem aproveitar. :slight_smile:

vlw Vini, o material do seu site é muito bom mesmo, esclareceu várias duvidas que eu tinha sobre como desenhar!

Pelo que eu entendi o Graphics2D somente desenha na tela, por exemplo, ao desenhar um círculo na tela não tem como mover esse círculo pra outra posição, tem que apagá-lo e desenhar outro círculo na posição desejada, correto?

E apagar não seria realmente excluir o círculo ou desfazer a pintura do mesmo, mas somente sobrepor com a cor do fundo?

[quote=ton.]vlw Vini, o material do seu site é muito bom mesmo, esclareceu várias duvidas que eu tinha sobre como desenhar!

Pelo que eu entendi o Graphics2D somente desenha na tela, por exemplo, ao desenhar um círculo na tela não tem como mover esse círculo pra outra posição, tem que apagá-lo e desenhar outro círculo na posição desejada, correto?

E apagar não seria realmente excluir o círculo ou desfazer a pintura do mesmo, mas somente sobrepor com a cor do fundo?[/quote]
Sim para ambas as perguntas.

O Graphics (ou, na maioria das vezes, o Graphics2D) é usado somente para fazer a renderização da imagem. Toda a lógica deve ser controlada separadamente pela sua aplicação.

E “apagar” na verdade é desenhar um retângulo com a cor de fundo sobre a tela anterior e fazer toda a renderização novamente.

Portanto como já dito, faça a renderização em paintComponent(). Como paintComponent() é definido em JComponent a classe JApplet não extende JComponent, faça a renderização em um painel separado e apenas adicione esse painel ao seu Applet. Veja:

Classe PointPanel:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;

public class PointPanel extends JPanel {

	private static final long serialVersionUID = 1L;
	private List<Point> points;

	public PointPanel() {
		points = new ArrayList<Point>(); // instanciamos nossa lista de pontos
		// adicionamos os listeners
		addMouseMotionListener(new MouseAdapter() {
			@Override
			public void mouseMoved(MouseEvent e) { // ao mover, adiciona
				points.add(new Point(e.getX(), e.getY()));
				repaint();
			}
		});
		addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) { // ao clicar, limpa
				points.clear();
				repaint();
			}
		});
	}

	@Override
	protected void paintComponent(Graphics g) {
		Graphics2D g2d = (Graphics2D) g.create(); // cria uma cópia do contexto
		g2d.setColor(Color.WHITE); // vamos pintar o fundo de branco
		g2d.fillRect(0, 0, getWidth(), getHeight()); // desenhamos o retângulo
		g2d.setColor(Color.RED); // os pontos serão vermelhos
		// ativamos o antialiasing para os círculos serem mesmo círculos
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		for (Point p : points) { // para cada ponto na lista
			g2d.fillOval(p.x, p.y, 5, 5); // desenhamos-no na posição
		}
		g2d.dispose(); // por fim, liberamos a cópia desse contexto para que a
		// área seja desenhada de fato
	}

}

Classe NewJApplet:

import javax.swing.JApplet;

public class NewJApplet extends JApplet {

	private static final long serialVersionUID = 1L;

	@Override
	public void init() {
		add(new PointPanel());
	}

}

marco, muuuuuito obrigado, eu tentei usar o paintComponent pensando que era algum método de Applet sem sucesso^^

Nesse seu exemplo, a cada movimento do mouse ele “apaga” o desenho e redesenha cada ponto, eu tinha pensado nisso mas achei melhor perguntar aqui pra ver se havia alguma forma de não ter que redesenhar tudo a cada movimento, uma forma seria pintar com a cor do fundo somente aquilo que vc deseja apagar, mas não éuma tática muito atraente^^

Outra coisa, na sua função ele adiciona um círculo a cada movimento do mousee dependendo da velocidade do movimento fica um risco grosso ou se fragmenta em vários círculos, quando é rápido, tem alguma coisa que pode ser feita pra impedir essa fragmentação? ou é uma limitação do Applet?

Na verdade essa é uma limitação quanto ao tempo de processamento entre um evento e outro.

Uma Thread separada (AWT-EventQueue) é encarregada de despachar os eventos para todos os listeners (inclusive sua classe). Mas isso geralmente leva alguns milissegundos. Como o processamento é assíncrono à repintura da janela, esse espaços ficam aí mesmo.

Um possível solução é fazer uma linha entre um ponto e outro (para uma linha simples, use o método drawLine; para soluções mais profissionais - e consequentemente mais complexas - esqueça esse List de Point e use um General Path, exemplo aqui).

Retificando o que eu disse, esqueça completamente aquele List de Point: Com GeneralPath é infinitamente melhor. Veja:

public class DrawPanel extends JPanel {

	private static final long serialVersionUID = 1L;
	private List<GeneralPath> paths;
	private int currentIndex;

	public DrawPanel() {
		paths = new LinkedList<GeneralPath>();
		currentIndex = -1;
		addMouseMotionListener(new MouseAdapter() {
			@Override
			public void mouseDragged(MouseEvent e) {
				if (e.getButton() != MouseEvent.BUTTON1
						&& e.getButton() != MouseEvent.NOBUTTON) {
					return;
				}
				if (currentIndex == -1) {
					currentIndex = paths.size();
					paths.add(currentIndex, new GeneralPath());
					paths.get(currentIndex).moveTo(e.getX(), e.getY());
				} else {
					paths.get(currentIndex).lineTo(e.getX(), e.getY());
				}
				repaint();
			}
		});
		addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				if (e.getButton() == MouseEvent.BUTTON3) {
					paths.clear();
					currentIndex = -1;
					repaint();
				}
			}

			@Override
			public void mouseReleased(MouseEvent e) {
				if (currentIndex != -1) {
					currentIndex = -1;
					repaint();
				}
			}
		});
	}

	@Override
	protected void paintComponent(Graphics g) {
		Graphics2D g2d = (Graphics2D) g.create();
		g2d.setColor(Color.WHITE);
		g2d.fillRect(0, 0, getWidth(), getHeight());
		g2d.setColor(Color.RED);
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		for (GeneralPath p : paths) {
			g2d.draw(p);
		}
		g2d.dispose();
	}

}

Adicione uma instância dessa classe ao seu JApplet e veja a diferença. Botão esquerdo desenha, clique com o direito apaga.

Nossa, muito melhor!!

Vou ler mais sobre Paths pq certamente vou usar^^

vlw marco!!

eu achei que Applets não reconheciam os diferentes botões do mouse por terem que funcionar em computadores Apple tb, mas sempre tem um jeitinho^^

Pra usar paintComponent, tem que ter uma classe que extende JPanel, porém, os métodos getWidth e getHeight não funcionam…

Tem outros métodos que poderiam me retornar a largura e altura do applet, ou eu devo usar esses msm no Applet e passar como parâmetros na criação do JPanel?

[quote=ton.]Pra usar paintComponent, tem que ter uma classe que extende JPanel, porém, os métodos getWidth e getHeight não funcionam…

Tem outros métodos que poderiam me retornar a largura e altura do applet, ou eu devo usar esses msm no Applet e passar como parâmetros na criação do JPanel?[/quote]
Não entendi direito qual a dúvida. Os métodos que você disse não funcionam em que classe? E o que você está precisando fazer?