JButton com imagem BACKGROUND

Galera,

Estou precisando colocar uma imagem de fundo em um JButton porém todos os exemplos que tentei não deram certo. Alguém já implementou isso e que possa me dar uma força?

Abraços :wink:

Galera,

Consegui fazendo Override do método paintComponent, porém como nem tudo é perfeito o texto do botão não aparece. Vi que posso usar o método drawString, porém o texto do meu botão é de mais de uma linha (formatado com html) e essa formatação html não funciona no método drawString.

Alguma sugestão :?:

public void paintComponent(Graphics g) {
        ImageIcon imagem = new ImageIcon(this.getClass().getResource(background));
        final Image backgroundImage = imagem.getImage();
        double scaleX = getWidth() / (double)backgroundImage.getWidth(null);
        double scaleY = getHeight() / (double)backgroundImage.getHeight(null);
        AffineTransform xform = AffineTransform.getScaleInstance(scaleX, scaleY);
        ((Graphics2D)g).drawImage(backgroundImage, xform, this);
        ((Graphics2D)g).drawString(textImage,  getWidth(), getHeight());
    }

Se você viu o código-fonte de javax.swing.JButton, pode ver que é realmente complexo desenhar um JButton. Não consigo lhe apontar uma solução muito melhor que a que você fez.
Se você usar o SwingX talvez possa usar o JXButton em vez do JButton.

Para chegar a um resultado aceitável o que eu fazia era litralmente criar um botão através de um JPanel. Você pode ver algums exemplos disso no livro Swing Hacks.

Eu sei q o link abaixo é para um panel, mas isso pode ajudar se vc for seguir a idéia q comentei:
http://blogs.sun.com/scblog/entry/tip_background_image_in_a

[quote=thingol]Se você viu o código-fonte de javax.swing.JButton, pode ver que é realmente complexo desenhar um JButton. Não consigo lhe apontar uma solução muito melhor que a que você fez.
Se você usar o SwingX talvez possa usar o JXButton em vez do JButton.
[/quote]
Vou fazer uns testes com esse componente para ver.

[quote=bobmoe]Para chegar a um resultado aceitável o que eu fazia era litralmente criar um botão através de um JPanel. Você pode ver algums exemplos disso no livro Swing Hacks.

Eu sei q o link abaixo é para um panel, mas isso pode ajudar se vc for seguir a idéia q comentei:
http://blogs.sun.com/scblog/entry/tip_background_image_in_a[/quote]
O background no botão já tá tranquilo. O unico problema agora é centralizar o texto na imagem de background do botão, pois esse texto pode variar de tamanho, dependendo da condição.

Galera,

Depois de quase desistir, finalmente consegui. Vejam:

[code]
public void paintComponent(Graphics g) {
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
ImageIcon imagem = new ImageIcon(this.getClass().getResource(background));
final Image backgroundImage = imagem.getImage();
double scaleX = getWidth() / (double) backgroundImage.getWidth(null);
double scaleY = getHeight() / (double) backgroundImage.getHeight(null);
AffineTransform xform = AffineTransform.getScaleInstance(scaleX, scaleY);
((Graphics2D) g).drawImage(backgroundImage, xform, this);

    // Find the size of string s in font f in the current Graphics context g.
    Font font = new Font("Dialog", Font.PLAIN, 11);
    FontMetrics fm   = g.getFontMetrics(font);
    java.awt.geom.Rectangle2D rectDescRamal = fm.getStringBounds(descRamal, g);
    java.awt.geom.Rectangle2D rectNumRamal = fm.getStringBounds(numRamal, g);

    int textHeightDR = (int)(rectDescRamal.getHeight()); 
    int textWidthDR  = (int)(rectDescRamal.getWidth());
    int textHeightNR = (int)(rectNumRamal.getHeight()); 
    int textWidthNR  = (int)(rectNumRamal.getWidth());        
    
    int panelHeight= this.getHeight();
    int panelWidth = this.getWidth();

    // Center text horizontally and vertically
    int xDR = (panelWidth  - textWidthDR)  / 2;
    int xNR = (panelWidth  - textWidthNR)  / 2;        

    g.drawString(descRamal, xDR, 20);  // Draw the string.
    g.drawString(numRamal, xNR, 34); 
}[/code]

O link que me salvou foi: http://www.leepoint.net/notes-java/GUI-appearance/fonts/18font.html

Realmente é um otimo jeito (Parabéns), porém se for necessario o uso de icone e texto html, fiz esta classe que resolveu meu problema.
Deste modo você nao perde as propriedades do Botao, alem de ganhar mais com o Painel

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionListener;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

/**
 * Botao com imagem de fundo
 * @author Cassio Lemos
 *
 */
public class MergedButton extends JPanel {

	private Image imgBkg;
	private JButton btn;
	
	public MergedButton(JButton btn, Icon ico, String label, ActionListener al, String srcImg) {
		super();
		
		this.setMaximumSize(btn.getMaximumSize());
		this.setMinimumSize(btn.getMinimumSize());
		this.setPreferredSize(btn.getPreferredSize());
		
		this.imgBkg = new javax.swing.ImageIcon(srcImg).getImage();
		
        btn.applyComponentOrientation(getComponentOrientation());
        btn.setIcon(ico);
        btn.setFocusPainted(false);
        btn.setFocusable(false);
        btn.setRequestFocusEnabled(false);
        btn.setHorizontalTextPosition(SwingConstants.CENTER);
        btn.setContentAreaFilled(false);//obrigatorio - fundo transparente
        btn.setVerticalTextPosition(SwingConstants.BOTTOM);
        //btn.setMargin(new Insets(1, 1, 20, 50));
        btn.setForeground(Color.WHITE);
        //btn.setBackground(new Color(7, 41, 89));
        btn.setHorizontalAlignment(SwingConstants.CENTER);
        btn.setText(label);
        btn.addActionListener(al);
        
        this.btn = btn;
        
        this.setLayout(new BorderLayout());
		this.add(btn, BorderLayout.CENTER);
	}
	
	public JButton getButton(){
		return this.btn;
	}
	
	 @Override  
	    public void paintComponent(Graphics g) {
	        super.paintComponent(g);   
	        if (imgBkg != null)  {
	        	g.drawImage(imgBkg, 0, 0, this);
	        }
	    } 
	
	
	
}