Editando JButton

Pessoal, preciso de alguns métodos para editar o JButton.

1- Colocar imagem como fundo
2- Preciso colocar o botão bem pequeno com apenas um número (Variações de 1 à 3), mas fica “…” no botão, por causa da margem, tería como tirar? Para o número aparecer preciso colocar um botão bem maior.
3- Editar o espaçamento entre os botões
4- Editar o tamanho da borda do botão.

Fugindo um pouco do tema, que método eu uso para executar um som quando clico em um botão?

Desculpe, pessoal, não sei quase nada de Swing.

Se me passarem um manual do JButton (de preferência em português) eu já agradeceria muito!

Obrigado!

Pra colocar a imagem:

Icon icone = new ImageIcon("icone.gif"); 
// Cria o botão 
JButton botao = new JButton("Botão"); 
// Seta a imagem pro botão 
botao.setIcon(icone); 

Tente colocar a imagem do número, talvez as margens se adaptem e não apareceça os …

Que tipo de som você pretende emitir? wave, midi?

O espaçamento entre os botões você tem que gerenciar com o Layout. Use um GridLayout que é beleza.

Você pode sempre alterar a fonte do botão, metendo as letras e os números mais pequenos.

Se quiser alterar o tamanho e posicionar os botões à sua medida use o layout(null).

Colocar as imagens no lugar das letras funcionou perfeitamente! A margem se ajustou.
Já estou usando o Grid, eu me lembro que tem um método para alterar o tamanho da borda, alguém lembra?
Pode ser um wave mesmo, é possível?
Eu estava tentando definir os padrões sem antes utilizar o “layout(null)” por isso não deveria estar indo! Vou testar aqui.

Abaixo um exemplo de como tocar wav e midi

import java.awt.*;
import java.awt.event.*;
import java.io.*;

// Pacotes de extensão de Java
import javax.swing.*;

public class ClipPlayerTest extends JFrame {
// objeto para reproduzir clipes de áudio
    private ClipPlayer clipPlayer;
// construtor para ClipPlayerTest
    public ClipPlayerTest() {
        super("Clip Player");

// painel contendo botões
        JPanel buttonPanel = new JPanel();
        getContentPane().add(buttonPanel);
// botão de abrir arquivo
        JButton openFile = new JButton("Open Audio Clip");
        buttonPanel.add(openFile, BorderLayout.CENTER);
// registra ActionListener para eventos de openFile
        openFile.addActionListener(
                // classe interna anônima para tratar o ActionEvent de openFile
                new ActionListener() {
// tenta abrir e reproduzir um arquivo de clipe de áudio
            public void actionPerformed(ActionEvent event) {
                File mediaFile = getFile();
                if (mediaFile != null) {
// instancia novo ClipPlayer com mediaFile
                    clipPlayer = new ClipPlayer(mediaFile);
// se o ClipPlayer foi aberto corretamente
                    if (clipPlayer.openFile() == true) {
// reproduz o clipe carregado
                        clipPlayer.play();
// sem repetição
                        clipPlayer.setReplay(false);
                    }
                } // fim do if mediaFile
            } // fim de actionPerformed
        } // fim de ActionListener
                ); // fim da chamada para addActionListener
    } // fim do construtor
// obtém o arquivo do computador
    public File getFile() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(
                JFileChooser.FILES_ONLY);
        int result = fileChooser.showOpenDialog(this);
        if (result == JFileChooser.CANCEL_OPTION) {
            return null;
        } else {
            return fileChooser.getSelectedFile();
        }
    }
// executa o aplicativo
    public static void main(String args[]) {
        ClipPlayerTest test = new ClipPlayerTest();
        test.setSize(150, 70);
        test.setLocation(300, 300);
        test.setDefaultCloseOperation(EXIT_ON_CLOSE);
        test.setVisible(true);
    }
} // fim da classe ClipPlayerTest
import java.io.*;

// Pacotes de extensão de Java
import javax.sound.sampled.*;

public class ClipPlayer implements LineListener {

// stream de entrada de áudio
    private AudioInputStream soundStream;
// linha de clipe de amostra de áudio
    private Clip clip;
// arquivo de clipe de áudio
    private File soundFile;
// booleana que indica repetição do áudio
    private boolean replay = false;
// construtor para ClipPlayer
    public ClipPlayer(File audioFile) {
        soundFile = audioFile;
    }
// abre arquivo de música, devolvendo true se bem-sucedido
    public boolean openFile() {
// obtém stream de áudio do arquivo
        try {
            soundStream = AudioSystem.getAudioInputStream(soundFile);
        } // arquivo de áudio não-suportado por JavaSound
        catch (UnsupportedAudioFileException audioException) {
            audioException.printStackTrace();
            return false;
        } // erro de E/S quando tentava obter stream
        catch (IOException ioException) {
            ioException.printStackTrace();
            return false;
        }
// invoca loadClip, devolvendo true se carga bem-sucedida
        return loadClip();
    } // fim do método openFile
// carrega clipe de som
    public boolean loadClip() {
// obtém linha de clipe para o arquivo
        try {
// obtém formato de áudio do arquivo de som
            AudioFormat audioFormat = soundStream.getFormat();
// define informações da linha com base no tipo de linha,
// codificação e tamanhos de frame do arquivo de áudio
            DataLine.Info dataLineInfo = new DataLine.Info(
                    Clip.class, AudioSystem.getTargetFormats(
                    AudioFormat.Encoding.PCM_SIGNED, audioFormat),
                    audioFormat.getFrameSize(),
                    audioFormat.getFrameSize() * 2);
// assegura que o sistema de som suporta linha de dados
            if (!AudioSystem.isLineSupported(dataLineInfo)) {
                System.err.println("Unsupported Clip File!");
                return false;
            }
// obtém recurso para a linha de clipe
            clip = (Clip) AudioSystem.getLine(dataLineInfo);
// espera por eventos da linha de clipe
            clip.addLineListener(this);
// abre clipe de áudio e obtém os recursos necessários do sistema
            clip.open(soundStream);
        } // fim do try
        // recurso de linha não-disponível
        catch (LineUnavailableException noLineException) {
            noLineException.printStackTrace();
            return false;
        } // erro de E/S durante interpretação dos dados de áudio
        catch (IOException ioException) {
            ioException.printStackTrace();
            return false;
        }

        // arquivo de clipe carregado com sucesso
        return true;

    } // fim do método loadClip

    // inicia reprodução do clipe de áudio
    public void play() {
        clip.start();
    }

    // método listener de eventos de linha para parar ou repetir no fim do clipe
    public void update(LineEvent lineEvent) {
        // se o clipe chega ao fim, fecha o clipe
        if (lineEvent.getType() == LineEvent.Type.STOP
                && !replay) {
            close();
        } // se repetição ligada, repete para sempre
        else if (lineEvent.getType() == LineEvent.Type.STOP
                && replay) {

            System.out.println("replay");

            // repete o clipe para sempre
            clip.loop(Clip.LOOP_CONTINUOUSLY);
        }
    }
// configura repetição do clipe
    public void setReplay(boolean value) {
        replay = value;
    }
// pára e fecha o clipe, devolvendo recursos do sistema
    public void close() {
        if (clip != null) {
            clip.stop();
            clip.close();
        }
    }
} // fim da classe ClipPlayer

Valeu, JoaoBluSCBR!

Funcionou perfeitamente!

Aproveitando o tópico, como eu faço para capturar o evento do botão direito do mouse?

No evento você faz uma verificacao para ver se eh o botao Direito:

this.addMouseListener(new MouseAdapter() {   
  
      public void mouseClicked(MouseEvent me) {   
          //Verificando se o botão direito do mouse foi clicado   
          if ((me.getModifiers() & MouseEvent.BUTTON3_MASK) != 0) {   
              //Daih coloca aqui o que vc quer que aconteca.  
  
          }   
      }   
  });  

Essa linha:

me.getModifiers() & MouseEvent.BUTTON3_MASK)

Compara os modificadores do evento com o valor do botao DIREITO

Valeu pela ajuda, tenho mais algumas dúvidas.

Por que tem apenas um “&” no if?
Por que ele só aceita variáveis final dentro dele? (tentei referenciar variáveis static e não consegui, do mesmo jeito que estava fazendo com o actionPerformed)
Tem alguma versão desse método pro Swing?

Esse & sozinho é um operador de comparacao AND.

Operador de comparacao de BITS

Ele compara o bit definido pela variavel final. Nao tem como usar diferente.

Mas acho que vc está confundindo as coisas. Para que vc quer modificar aquilo?

Aquela linha if é a que diz se vc clicou com o botao direito.

depois do if (denro da declaracao) você coloca qualquer coisa.

E isso serve para eventos de Mouse SWING. Não entendi o por que da pergunta.

E pra que vc precisa referenciar variaveis static. Crie tuas variaveis dentro da classe, como atributos.
o main só serve para iniciar a classe. pare de colocar nele codigo de execucao. Isso só vai te distanciar
da orientacao a objetos e vai ficar com um codigo cada vez mais truncado.

Se quiser poste o teu código da classe swing e me diga qual a tua duvida.

E eu te explico o que deve mudar.

Desculpe a demora, não tive tempo esses dias.

[code]
//Esse foi o único jeito que achei para funcionar para todos os quadrados (Estrou desenvolvendo um Campo Minado);
//Como ele importou isso da awt, foi por isso que perguntei se tinha algum parecido no pacote swing
MouseAdapter me = new MouseAdapter() {
public void mouseClicked(MouseEvent me) {

//No actionPerformed eu tinha o objeto “camp” e referênciava a estrutura utilizando “camp.estrutura”
//mas não consegui ele dentro do mouseClicked por isso converti para static, mas não funcionou também
//aí criei um get para pegar a estrutura
Quadrado[][] c = Campo.getEstrutura();

//mesma coisa aqui, tive que criar um get para utilizar o tamanho
//essa parte do código ele faz a verificação em todos os quadrados, para saber qual foi clicado
for (int i = 0; i < getTamanho(); i++){
for (int j = 0; j < getTamanho(); j++){
if (me.getSource() == c[i][j].botao){

//aqui ele vê se foi clicado com o boão direito
//essa parte que eu não entendi, não seria a mesma coisa colocar &&? Mas vi que && ele não aceita
if ((me.getModifiers() & MouseEvent.BUTTON3_MASK) != 0) {

// se sim, ele coloca uma bandeirinha no quadrado
if(c[i][j].bandeira == true){
c[i][j].bandeira = false;
}
else {
c[i][j].bandeira = true;
}
}
}
}
}
//aqui ele atualiza a interface
atualizarCampo();
}
};[/code]

Desculpe se alguma dessas perguntas foi idiota, estou começando agora.

Voce ainda nao aprendeu orientacao a objeto, nao eh?

Eh que usando a orientacao, quando vc clica no botao, vc ativa o evento dele.

E dentro da classe do botao esta o quadrado que pertence a ele.

Entao nao precisa rodar todos para ver se acha qual foi clicado.

Hoje nao posso, to elaborando uma prova para meus alunos.

Mas amanha prometo que comeco a tentar te explicar como isso funciona.

Entendi, se puder me explicar melhor eu agradeço!

Estarei aguardando!

Olah , prometi ajudar e hoje aqui estou.

Em anexo coloquei um projetinho que fiz, soh o basico para vc entender.

O negocio eh o seguinte.

O invés de instanciar JButtons e quadrado e ficar tentando emparceiras cada um deles para ver esse foi clicado ou aquele foi clicado, usei Orientacao a Objetos.

Criei a classe Quadrado que extende JButton (explicando, caso nao saiba) Quadrado eh a tua classe mas ele herda (recebe automaticamente) todos os metodos de JButton, ou seja eh um botao como qualquer outro do swing, apenas eh tbm um Quadrado que pode ter uma bomba, e pode mostrar uma bandeira.

Tbm criei uma classe de tela. Inseri um monte de botoes nela (JButton) por que é isso que eu posso usar graficamente.

Daí usei o personalizar codigo de cada um dos botoes e troquei a inicializacao dele por um Quadrado. Ou seja cada JButton passa a ser um Quadrado e conter as informacoes que eu quiser colocar nele usando os sets e gets que criei para assinalar que tem bomba ou bandeira.

Ainda na tela fiz um atributo criando um array de quadrados, apenas para caso eu precise sortear um Quadrado onde colocar minhas bombas.
E usei um metodo para ligar cada elemento do array com o meu botao fisico que ja esta instanciado como um quadrado. Pronto agora eu posso usar o array de Quadrados para sortear onde colocar as bombas.

Agora vem a questao dos eventos.

Ao inves de colocar os eventos em cada botao da Tela. Eu coloque apenas na classe Quadrado. Entao quando eu clico num botao na tela. Ela aciona o evento daquele botao e verifica se foi clicado com a direita ou nao.

Eh bem simples de fato, mas voce pode melhor muito a classe quadrado e fazer tudo que voce precisar.

Pode por exemplo criar em cada classe quadrado um array de 8 quadrados que seriam os seus adjacentes e ligar cada um deles. Assim, por exemplo, quando voce quisesse contar quantas bombas tem nas casas adjacentes bastaria passar esse array acumulando os isBombas de cada um.

Fica tudo mais facil assim. Por que vc organiza melhor. Quadrado cuida de suas coisas. A classe tela não precisa ficar correndo o array de quadrados para ver se foi ou nao foi clicado em um botao. Quando clicou eh naquele botao que o evento serah disparado.

Se nao tiver entendido algo me fale, tento explicar melhor. Explicar eh o que faco melhor, pelo menos eh o que os meus alunos me dizem. Bando de puxa-sacos. kkkkk

abs

Obrigado, JoaoBluSCBR!

Irei aproveitar o sábado para tentar melhorar meu código, em breve reporto aqui as melhorias (ou dúvidas)!

JoaoBluSCBR, usei a sua explicação para melhorar o meu código, acho que estou no caminho certo. Porém, creio que terei que fazer outra lógica para verificar as bombas em volta do quadrado clicado, pois eu estava usando uma matriz (e construindo o campo graficamente igual a matriz), um trecho do código:

//Aqui eu só criei vários ifs para diferenciar se o quadrado está no meio do campo ou em alguma das laterais extremas, evitando um ArrayIndexOutOfBoundsException
private void espaçosAdjacentes(Quadrado [][] campo, int y, int x){
		if (y<(InterfaceGrafica.tamanho)-1 && y>0){
			if(x == (InterfaceGrafica.tamanho)-1){
				for (int i=-1;i<2;i++){
					for (int j=-1;j<1;j++){
						if (campo[y+i][x+j].verificarMina()){

//Aqui ele vai somando o número de minas em volta.
							campo[y][x].numeroDoQuadrado++;

						}			
					}
				}
			}
			else if (x==0){
				for (int i=-1;i<2;i++){
					for (int j=0;j<2;j++){
						if (campo[y+i][x+j].verificarMina()){
							campo[y][x].numeroDoQuadrado++;
						}			
					}
				}
			}
			else if (x>0 && x<(InterfaceGrafica.tamanho)-1){
				for (int i=-1;i<2;i++){
					for (int j=-1;j<2;j++){
						if (campo[y+i][x+j].verificarMina()){
							campo[y][x].numeroDoQuadrado++;
						}			
					}
				}
			}
		}
		
		else if (y==0){
			if (x < (InterfaceGrafica.tamanho)-1 && x > 0){
				for (int i=0;i<2;i++){
					for (int j=-1;j<2;j++){
						if (campo[y+i][x+j].verificarMina()){
							campo[y][x].numeroDoQuadrado++;
						}			
					}
				}
			}
			
			else if (x==0){
				for (int i=0;i<2;i++){
					for (int j=0;j<2;j++){
						if (campo[y+i][x+j].verificarMina()){
							campo[y][x].numeroDoQuadrado++;
						}			
					}
				}
			}
			else {
				for (int i=0;i<2;i++){
					for (int j=-1;j<1;j++){
						if (campo[y+i][x+j].verificarMina()){
							campo[y][x].numeroDoQuadrado++;
						}			
					}
				}
			}
		}
		
		else{
			if (x < (InterfaceGrafica.tamanho)-1 && x >0){
				for (int i=-1;i<1;i++){
					for (int j=-1;j<2;j++){
						if (campo[y+i][x+j].verificarMina()){
							campo[y][x].numeroDoQuadrado++;
						}			
					}
				}	
			}

			else if(x == (InterfaceGrafica.tamanho)-1){
				for (int i=-1;i<1;i++){
					for (int j=-1;j<1;j++){
						if (campo[y+i][x+j].verificarMina()){
							campo[y][x].numeroDoQuadrado++;
						}			
					}
				}
			}
			
			else {
				for (int i=-1;i<1;i++){
					for (int j=0;j<2;j++){
						if (campo[y+i][x+j].verificarMina()){
							campo[y][x].numeroDoQuadrado++;
						}			
					}
				}
			}
		}
		
		if (campo[y][x].numeroDoQuadrado == 0){
//Se não tiver nenhuma mina envolta, ele faz as verificações em todos os quadrados envolta.
			verificarQuadradosAdjacentes(campo, y, x);
		}	
	}

O único jeito que achei foi dando coordenadas para o botão ou fazer todas as verificações mesmo.

Uma outra dúvida, criei um “revelarCampo()” que revela todo o campo quando o jogo termina, mas eu queria que ele fosse revelando casa por casa, então criei esse trecho de código:

    public void revelarCampo() throws Exception{
    	try{
    		for (int h = 0; h < tamanho; h++){
    			for (int g = 0; g < tamanho; g++){

                                //Aqui ele vai abrindo um por um dos quadrados
    				estrutura[h][g].setAberto(true);

                                //Esse método atualiza todos os icons do campo minado
    				atualizarCampo();

                                //Uma pausa se não vai absurdamente rápido
    				Thread.sleep(500);
                        }
    		}
    	}
    	    	
    	finally{
    	}
    }

Eu até tinha criado a atualização dos icons no próprio método e também não funcionou.
Ele só atualiza o campo Depois que o for acaba, durante a execução do for não acontece nada.

Podería me ajudar com isso? Obrigado.

É muito ruim ir para a segunda página, as vezes eu acho que o pessoal nem vê que existe uma segunda página :lol:

Até agora não consegui resolver esse problema :cry:

Nao recebi o email do seu post anterior, soh desse ultimo reclamando da mudança de página.

Vou dar uma olhada no seu código.

Mas creio que voce ja se perdeu na orientacao a objetos novamente.

Voce pode usar arrays mas tem que lembrar que cada objeto vai responder por suas acoes.

E a ligacao entre casas adjacentes dependem de uma organizacao previa para isso.

Seria mais fácil se voce me mandasse todo ele para eu montar e ver no que posso ajudar.

Se quiser compacte e mande para

joao.neumann.neto@pq.cnpq.br

Imagine uma classe de Tabuleiro. Nessa classe está o teu array bidimensional de Quadrados, conforme a tabela:
[0][0] [0][1] [0][2] [0][3] [0][4] [0][5]
[1][0] [1][1] [1][2] [1][3] [1][4] [1][5]
[2][0] [2][1] [2][2] [2][3] [2][4] [2][5]
[3][0] [3][1] [3][2] [3][3] [3][4] [3][5]
[4][0] [4][1] [4][2] [4][3] [4][4] [4][5]
[5][0] [5][1] [5][2] [5][3] [5][4] [5][5]
Um quadrado em [0][0], outro em [0][1] e assim sucessivamente.
É preciso instancia-los todos antes de qualquer outro procedimento. E ligá-los com os botões de tela. Pra que os eventos respondam por eles.
Agora…Dentro de cada quadrado há um array de seus vizinhos. Um array de no máximo 8 quadrados que apontam para cada um dos quadrados vizinhos.
Não serão criados novos Quadrados. Neste array apontaremos cada um dos quadrados já criados no tabuleiro para fim de podermos contar suas bombas depois.
Como obte-los. Buscando na classe do tabuleiro com um método que pode ter a seguinte assinatura:

public Quadrado getQuadrado(int x, int y){ return arrayQuadrados[x][y]; }
A instancia do tabuleiro pode ser passado na construção de cada quadrado. Assim ele já saberá onde encontrar o tabuleiro e pegar de lah o nome de seus vizinhos.
Como preencher os vizinhos no array:
No construtor de um quadrado ele receberá do tabuleiro seu x e y que dever ser registrados em atributos. Com estes valores e o numero de linhas e colunas é fácil fazer um loop que carregue os vizinhos.
Por exemplo: Se for o Quadrado [0][0] quais são seus vizinhos:
São os menores que x, os iguais a x e os maiores que x, todos em 1 unidade. Então serão os [-1][0], [0][0] e o [1][0]. Negativos não existem. [0][0] é o próprio quadrado então se descarta, sobra apenas [1][0] como primeiro vizinho válido.
Próxima etapa, os menos que y, os iguais a y e os maiores que y, todos em 1 unidade. Então temos os [0][-1], [0][0], [0][1]. Novamente -1 não é válido. [0][0] é próprio e resta de válido o [0][1]. Agora temos dois vizinhos válidos.
Última etapa analisar as diagonais: As diagonais são sempre quatro feitas com --, -+. ± e ++, ou seja [-1][-1], [-1][1], [1][-1], [1][1]. Descartamos as que tem qualquer numero negativo e resta apenas [1][1].
Ou seja, nosso Quadrado[0][0] tem como vizinhos validos [1][0], [0][1] e [1][1].
Ou seja, um método preencher vizinhos preencheria o primeiro vizinho com aquele Quadrado que estah no tabuleiro na posição [1][0] e depois o de [0][1] e por ultimo o em [1][1].
Um quadrado central terá os 8 quadrados calculados da mesma forma e um quadrado da extrema direita, ou de baixo terá vizinhos a expurgar que sejam maiores que o numero de linhas e colunas. Mas a formula eh a mesma.
Então a partir dessa explicação, o que devemos expurgar:
1 ? o próprio quadrado
2 ? qualquer quadrado que tenha um índice menor que zero.
3 ? qualquer quadrado que tenha um índice coluna maior que o nr de colunas
4 ? qualquer quadrado que tenha um índice linha maior que o nr de linhas
Vamos por isso em código:

[code]public class Quadrado extends JButton{
private int x;
private int y;
private Quadrado[] vizinhos = new Quadrado[8];
private int contaVizinhos = 0;
public void prencherArrayVizinhos( ){
int xtotal = tabuleiro.getNrLinhas()-1;
int ytotal = tabuleiro.getNrColunas()-1;
for (int lin = x-1; lin<=x+1; lin++){
for( int col = y-1; col<=y+1; col++){
//Verificando
If(x==lin)&&(y==col)
Continue;
If(lin<0) || (col<0)
Continue;
If(lin>xtotal)||(col>ytotal)
Continue;
//Chegou aki eh um vizinho valido
vizinhos[contaVizinhos++] = tabuleiro.getQuadrado(lin, col);
}
}

            public int getNrBombasVizinhas(){
                int nr = 0;
                for(int i=0; i<contaVizinhos;i++){
	                if(vizinhos[i].isBomba())
		              nr++;
                }
                return nr;
            }

}
[/code]
Espero que isso ajude a voce nao fazer tanto codigo dependendo de cada posicao do tabuleiro.

Lembre, principalmente em tabuleiros quadraticos sempre tem uma forma de analise que
reduz muito os ifs.

No final das contas esse meu codigo abaixo substitue os teus ifs todos em apenas isso:

int xtotal = tabuleiro.getNrLinhas()-1; int ytotal = tabuleiro.getNrColunas()-1; for (int lin = x-1; lin<=x+1; lin++){ for( int col = y-1; col<=y+1; col++){ //Verificando If(x==lin)&&(y==col) Continue; If(lin<0) || (col<0) Continue; If(lin>xtotal)||(col>ytotal) Continue; //Chegou aki eh um vizinho valido vizinhos[contaVizinhos++] = tabuleiro.getQuadrado(lin, col); } }