MouseEvent

Boa tarde,
sei que tem vários posts falando sobre MouseEvent, mas não consegui sanar a minha dúvida em nenhum deles.

Estou fazendo um jogo (player x pc) de batalha naval. Ele pega o nome do jogador, cria o tabuleiro com JButtons e na hora de pedir para o usuário posicionar os navios que eu não consigo.
Como faço para pedir que o usuário selecione, por exemplo, 5 botões para posicionar o porta-aviões?
Já usei o MouseEvent em outros joguinhos que eu desenvolvi, mas nada precisava pedir ao usuário para selecionar vários ao mesmo tempo.

Agradeço desde já a ajuda de todos!

Bom, eu nunca fiz algo parecido com isso, mas, creio que isso talvez funcione.

  • Crie uma lista de pontos, que representa os locais (JButton) onde o usuário posicionou um item.
  • Crie uma action para o evento click, adicione o mesmo a todos os botões (lembre-se, todos os botões aceita mais de um evento)
  • Nesta action, cada clique vai incrementar um contador e vai adicionando a referência do botão selecionado na lista criada no primeiro item
  • Quando chegar a 5, aí bloqueia a adição e informa a mensagem que todas as posições foram selecionadas.

Ficou mais claro?

Boa tarde Darlan, agradeço a força.
Já criei a lista de pontos e todos os botões estão com action para o evento adicionado.
A minha dúvida é como esperar o usuário selecionar um (ou mais) botão.

public void posicionaNaviosPlayer() {

	Navio navio;

    //entra no for para posicionar cada um dos 5 navios disponíveis.
	for(int i = 1; i <= 5; i++) {

		navio = constroiNavio(i, player);

		JOptionPane.showMessageDialog(
				null, "Posicione o " + navio.getNome() + "."
				+ "\nVocê precisa selecionar " + navio.getTamanho() + " espaços."
				+ "\nPara isso, bastar clicar aonde deseja posicionar."
				+ "\nLembre-se, todas as partes devem estar juntas.");

        //Guarda os botões selecionados
		Botao [] botoes = new Botao [navio.getTamanho()];

        //AQUI ESTÁ A DÚVIDA.
		for(int j = 0; j < navio.getTamanho(); j++) {

			
		}
	}
}

No segundo “for” ele pega o tamanho do navio. Ai é que eu não sei como esperar o usuário selecionar os botões.

Recomendo usar JLabel que é mais fácil, depois crie um tabuleiro com os labels já instanciados:

label.addMouseListener(new MouseAdapter() {
  public void mouseEntered(MouseEvent me) {
    if (estado == EDICAO) {
      int xi = label.obterX();
      int yi = label.obterY(); // índices relativo ao tabuleiro
      int xf = xi, yf = yi; // i de inicio, f de fim
      if (navio é horizontal) {
       xf += navio.tamanho;
      }
      if (navio é vertical) {
       yf += navio.tamanho;
      }
      if (xf e yf estão dentro do tabuleiro) {
        atribuiBordaVerde(labels de xi a xf e yi a yf);
      } else {
        atribuiBordaVemelha(labels de xi a xf e yi a yf);
      }
    }
  }
  public void mouseExited(MouseEvent me) {
    removeBordaDosLabel();
  }
  public void mouseClicked(MouseEvent me) {
    if (estado == EDICAO) {
      int xi = label.obterX();
      int yi = label.obterY(); // índices relativo ao tabuleiro
      int xf = xi, yf = yi; // i de inicio, f de fim
      if (navio é horizontal) {
       xf += navio.tamanho;
      }
      if (navio é vertical) {
       yf += navio.tamanho;
      }
      if (xf e yf estão dentro do tabuleiro) {
        atribuiNavioAsoLabels(labels de xi a xf e yi a yf);
      } else {
        imprimeErro;
      }
    }
  }
});

void atribuiNavioAosLabels(xi, yi, xf, yf, navio) {
 int i = 0;
 for (yi até yf) {
   for (xi até xf) {
     label[yi][xi].atribuirParte(navio.obterParte(i));// supondo que o navio é dividido em partes
     i += 1;
   }
 }
}

Obrigado Diego, acho que consegui entender.
Quando implementar eu coloco aqui se deu certo ou não.

Eu achei que tinha entendido, mas não sei se estou colocando o código no lugar errado ou se não entendi como usar.
Troquei para JLabel como você sugeriu, diego12.
Mas ainda assim, quando peço para o usuário posicionar o navio, ainda não consegui esperar pelos ‘cliques’ do usuário, continua passando direto pro ‘próximo navio’ e ficando tudo vazio.

@IghorSantiago eu acredito que para sua solução seria melhor criar duas matrizes uma para o tabuleiro e outra que vai ser de JButtons ou JLabels como vc quiser acho que com isso vai ajudar muito a vc a realizar

esse foi um jogo de guerra naval onde os navios são posicionados no tabuleiro de forma randômica ver se isso pode te ajuda

Obrigado Manasses_Eugenio pela ajuda.
A parte randômica eu vou usar pra fazer o tabuleiro do computador, assim que eu terminar o do usuário.
No momento eu estou tentando pedir para o usuário escolher os labels em que vão ficar os navios e isso é armazenado em um vetor, para depois jogar na matriz.
A única coisa que falta é conseguir esperar a ação do usuário.
Mesmo com 2 matrizes eu vou cair no mesmo problema, vou ter que pegar o clique para posicionar os navios.

A vantagem de usar Labels são os eventos como enter, click e exited, que funcionam melhor que nos Buttons.

import javax.swing.*;
import java.awt.*;
import javax.swing.border.Border;

public class Botao extends JLabel
{
    static final Border BORDA_PADRAO = BorderFactory.createLineBorder(Color.BLACK, 3);
    static final Border BORDA_VERDE = BorderFactory.createLineBorder(Color.GREEN, 3);
    static final Border BORDA_VERMELHA = BorderFactory.createLineBorder(Color.RED, 3);
    
    Point posicao;
    
    public Botao(int x, int y) {
        super();
        posicao = new Point(x, y);
        setOpaque(true);
        setBorder(BORDA_PADRAO);
        setBackground(Color.BLUE);
    }
}


import javax.swing.*;
import java.awt.*;
import javax.swing.border.Border;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class Janela extends JFrame
{
    Botao[][] botoes;
    public Janela() {
        super();
        botoes = new Botao[8][12]; // (y,x)
        for (int y = 0; y < 8; y++) {
            for (int x = 0; x < 12; x++) {
                botoes[y][x] = new Botao(x,y);
                getContentPane().add(botoes[y][x]);
                adicionarEvento(botoes[y][x]);
            }
        }
        setSize(600,400);
        getContentPane().setLayout(new GridLayout(8, 12));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    // variaveis de teste
    boolean horizontal = true;
    int tamanho = 3;
    
    void adicionarEvento(Botao b) {
        b.addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent me) {
                if (true) { // somente para teste, deve ser trocado para verificar se está "editando"
                    int xi = b.posicao.x;
                    int yi = b.posicao.y; // índices relativo ao tabuleiro
                    int xf = xi, yf = yi; // i de inicio, f de fim
                    if (horizontal) {
                        xf += tamanho - 1; // -1 inclusivo
                    } else { // senão é vertical
                        yf += tamanho - 1;
                    }
                    if (xf >= 0 && xf < 12 && yf >= 0 && yf < 8) {
                        atribuiBordaVerde(xi, yi, xf, yf);
                    } else {
                        atribuiBordaVemelha(xi, yi, xf, yf);
                    }
                }
            }
            public void mouseExited(MouseEvent me) {
                for (int y = 0; y < 8; y++) {
                    for (int x = 0; x < 12; x++) {
                        botoes[y][x].setBorder(Botao.BORDA_PADRAO);
                    }
                }
            }
        });
    }
    
    void atribuiBordaVerde(int xi,int yi, int xf, int yf) {
        atribuiBorda(xi, yi, xf, yf, Botao.BORDA_VERDE);
    }
    
    void atribuiBordaVemelha(int xi,int yi,int xf,int yf) {
        atribuiBorda(xi, yi, xf, yf, Botao.BORDA_VERMELHA);
    }
    
    void atribuiBorda(int xi,int yi,int xf,int yf, Border border) {
        while (yi <= yf) {
            while (xi <= xf) {
                if (xi >= 0 && xi < 12 && yi >= 0 && yi < 8) {
                    botoes[yi][xi].setBorder(border);
                }
                xi += 1;
            }
            yi += 1;
        }
    }
    
    public static void main(String[] args) {
        new Janela().setVisible(true);
    }
}
1 curtida

Já tinha trocado para JLabel o tabuleiro.
Obrigado mais uma vez diego12.
Vou tentar aqui com o código que você colocou.