Método paintComponent() apagando imagens no JFrame

1 resposta
java
Eowyn_1996

Eu preciso gerar um mapa de acordo com um arquivo txt que recebo como entrada. Cada tipo de letra do meu arquivo txt corresponde a um tipo de terreno do mapa. Criei arrays de Image que vão armazenar as imagens que posso usar para cada tipo de terreno e desenho essas imagens no Jframe. Já verifiquei e o caminho das imagens estão corretos, mas como eu chamo o método onPaint várias vezes durante a execução do programa, o mapa acaba sendo apagado (acredito que esse seja esse o motivo). Preciso desenhar o mapa apenas uma vez e, feito isso, movimentar um avatar sobre ele. Como faço pra desenhar o mapa, deixá-lo montado e redesenhar apenas o avatar conforme ele se movimenta?

Segue o código:

public class MapaInterface extends JPanel implements ActionListener {

BuscaHeuristicaGameOfThrones busca = new BuscaHeuristicaGameOfThrones();
private Image fundo;
private Image explosao = new ImageIcon("src/res/exp1.png").getImage();
private Image agua = new ImageIcon("/src/res/agua.png").getImage();
public static ArrayList<Image> grama = new ArrayList<>();
public static ArrayList<Image> terra = new ArrayList<>();
public static Agente daenerys;
private Timer timer;
FileReader arquivo = null;
BufferedReader leitor;
String linha = "";

public MapaInterface() {
    try {
        arquivo = new FileReader("mapaInvertido.txt");
        leitor = new BufferedReader(arquivo);
    } catch (FileNotFoundException ex) {
        Logger.getLogger(MapaInterface.class.getName()).log(Level.SEVERE, null, ex);
    }
    ImageIcon referencia = new ImageIcon("src/res/mapaGot2.png");
    fundo = referencia.getImage();
    timer = new Timer(1, this);
    preencheArrayDeImagens();
    timer.start();
    daenerys = new Agente();
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D graficos = (Graphics2D) g;
    Random random = new Random();
    int numAleatorio = random.nextInt(23);
    int x = 0, y = 0;
    String tipo = "";
    graficos.drawImage(new ImageIcon("src/res/terrinha.png").getImage(), x,y, this);
    try {
        linha = leitor.readLine();
        StringTokenizer tokenizer;
        while(linha != null){
            tokenizer = new StringTokenizer(linha, ",");
           while(!tipo.equals("|")){
                tipo = tokenizer.nextToken();
                if (tipo.equals("T")) {
                    graficos.drawImage(terra.get(numAleatorio), x, y, null);
                    g.dispose();
                }
                if (tipo.equals("G")) {
                    graficos.drawImage(grama.get(numAleatorio), x, y, null);
                }
                if (tipo.equals("A")) {
                    graficos.drawImage(agua, x, y, null);
                }
                x += 16;
            }
            y+=16;
            linha = leitor.readLine();
        }
    } catch (IOException ex) {
        Logger.getLogger(MapaInterface.class.getName()).log(Level.SEVERE, null, ex);
    }
    graficos.drawImage(daenerys.getImagem(), daenerys.getPosicaoMI().getX(), daenerys.getPosicaoMI().getY(), this);
    if (daenerys.chegouDestino == true) {
        graficos.drawImage(explosao, daenerys.getPosicaoMI().getX(), daenerys.getPosicaoMI().getY(), this);
        daenerys.chegouDestino = false;
    }
    g.dispose();
}

@Override
public void actionPerformed(ActionEvent e) {
    if (daenerys.destinoMuralha == true) {
        if (daenerys.chegouMuralha == false) {
            daenerys.movimentaAgenteMuralha();
            repaint();
        } else {
        }
    } else {
        daenerys.movimentaAgente();
    }
    repaint();
}

public static Agente getDaenerys() {
    return daenerys;
}

public static void setDaenerys(Agente daenerys) {
    MapaInterface.daenerys = daenerys;
}

public void preencheArrayDeImagens() {
    Image blocoTerra = new ImageIcon("src/res/cogumeloterra.png").getImage();
    terra.add(blocoTerra);
    blocoTerra = new ImageIcon("src/res/fogueira.png").getImage();
    terra.add(blocoTerra);
    blocoTerra = new ImageIcon("src/res/tronco.png").getImage();
    terra.add(blocoTerra);
    blocoTerra = new ImageIcon("src/res/tronco2.png").getImage();
    terra.add(blocoTerra);

    Image blocoGrama = new ImageIcon("src/res/florbranca.png").getImage();
    grama.add(blocoGrama);
    blocoGrama = new ImageIcon("src/res/florvermelha.png").getImage();
    grama.add(blocoGrama);
    blocoGrama = new ImageIcon("src/res/matinho.png").getImage();
    grama.add(blocoGrama);
    blocoGrama = new ImageIcon("/src/res/cogumelovermelho.png").getImage();
    grama.add(blocoGrama);

    for (int i = 0; i < 20; i++) {
        grama.add(new ImageIcon("src/res/graminha.png").getImage());
        terra.add(new ImageIcon("src/res/terrinha.png").getImage());
    }
}

Fiz alguns testes e dessa forma funciona normalmente:

graficos.drawImage(terra.get(numAleatorio), 16, y, this);
    graficos.drawImage(terra.get(numAleatorio), 32, y, this);
    graficos.drawImage(terra.get(numAleatorio), 48, y, this);

Só que não posso fazer isso pois o tipo de terreno depende das letras no txt

1 Resposta

TerraSkilll

Não vou responder em cima do seu código porque faltam mais partes para entender como ele está estruturado. Mas aqui vão alguns comentários:

  • você está lendo o arquivo toda vez que o paintComponent é chamado. Não faça isso. Ler um arquivo é um processo lento demais para ser feito a cada chamada a paintComponent;
  • faça a leitura do arquivo1 vez só (ao iniciar o programa ou no construtor do JPanel), para uma outra estrutura (exemplo: ArrayList). No paintComponent, você desenha a partir dessa estrutura;
  • o paintComponent deve ser usado somente para os métodos de desenho. Toda a lógica que não for de desenho (ler arquivo, gerar coisas aleatórias, etc) deve ficar fora do paintComponent ;
  • o JFrame (que contém seu JPanel, suponho) precisa ser exibido usando a thread do Swing. Veja como em http://www.pontov.com.br/site/java/48-java2d/92-conhecendo-o-jframe , quase no final do artigo. Isso é importante para resolver diversos problemas de exibição do JFrame e do JPanel;

Recomendo a leitura dos artigos do Ponto V sobre java 2d ( http://www.pontov.com.br/site/index.php/java/48-java2d ). Lá fala sobre o loop de animação, algo que lhe será útil.

Abraço.

Criado 28 de julho de 2016
Ultima resposta 28 de jul. de 2016
Respostas 1
Participantes 2