Imagem no fundo do JTable (Como inserir uma imagem no background de um JTable)

Olá Pessoal!

Andei pesquisando na net e encontrei apenas um tópico sobre o assunto, mas testei e não funcinou!  :( 
Vejam: http://www.codeguru.com/java/articles/177.shtml

O objetivo é inserir uma imagem no fundo de um JTable de preferência com as linhas zebradas.
Alguem sabe como posso fazer isso?

Obrigado!

Cara… eu sei como colocar uma imagem JPanel… não sei se ajuda…

Da uma pesquisada em JImagePanel…

Abs

Boa pergunta, não sei se é possivel.

As celulas da JTable são renderizadas cada uma com um JComponent, talvez seja possivel criar uma classe que extenda JTable, renderizar uma imagem de fundo, e criar um CellRenderer que devolva um JComponent semi-transparente para ser colocada na tabela.

Dê uma olhada no link que passei, lá eles conseguiram fazer.
O grande problema é que aquele tópico é de 1999, então a versão da MVJ devia ser bem antiga.
Eu consegui inserir uma imagem na tabela, mas ela só aparece até onde tem linhas.

Para isso eu estendi um JTable e sobre-escrevi o método:

public void paint( Graphics g )
    {
        super.paint(g);
        Graphics2D g2d = (Graphics2D)g;
        g2d.drawImage(image.getImage(), 0, 0, this.getWidth(), this.getHeight(), null);
        g2d.dispose();
    }

Como posso fazer ele mostrar a imagem mesmo não existindo linhas?

  1. Você jamais deve sobrescrever o método paint de um componente do Swing;
  2. Você deve criar uma cópia do objeto Graphics passado por parâmetro;
  3. Você não deve dar dispose no objeto Graphics recebido por parâmetro;
  4. O que não funcionou no código que você passou? Ele me parece java bem padrão. Dá algum erro?

Acho que dependendo do Look & Feel, esse código que ele achou não vai funcionar.
Eu estou tentando usar um código semelhante ao que ele achou em uma JTable com Look & Feel Nimbus, e realmente não funciona (acho que o “setOpaque (false)” simplesmente não funciona com o SynthTableCellRenderer que é usado internamente pelo Nimbus :frowning: )
Pelo que imagino, teria de saber um monte de detalhes do Nimbus que só estudando o código para poder mexer.
(Só para dar um exemplo: como é que você muda a cor da JProgressBar do Nimbus, que é laranja? Não é trivial, e uma coisa pior ainda: se mudar essa cor para uma JProgressBar, muda de todos os outros ProgressBars. Que coisa absurda)

Veja a imagem em anexo.

A imagem de fundo da tabela aparece somente onde há linhas, entende?

Na minha necessidade a imagem deveria continuar a até o final da tabela.

Bom, pelo que eu sei dos componentes do Swing, geralmente é uma má idéia tentar modificar o desenho deles.
Ou a coisa já funciona por padrão, e ele te dá ganchos para isso, ou esqueça.

Ah, esse é outro problema.
Então não é o look & feel (já que você está usando o Metal ou o System) e sim o fato de o paint desse código só pintar, no seu caso, até Dimension d = getSize();
que é o tamanho da JTable dentro do JScrollPane.

Eu já coloquei o seguinte código e a imagem ficou cortada onde termina as linhas. :roll:

g2d.drawImage(image.getImage(), 0, 0, this.getWidth(), this.getHeight()+50, null);  

Quando você tenta pintar um componente Swing, se não me engano a pintura é “clipada” na dimensão que ele tem (a JTable vai só onde terminam as linhas, como você deve ter visto). Mesmo que você use esse artifício de somar 50 (poderia estar somando qualquer outro valor), continha a ficar “clipada”).

Não sei se é possível você pintar o JScrollPane e então deixar a JTable com setOpaque = false; só testando (e lembrando que setOpaque não funciona direito para o que você quer fazer no Look & Feel Nimbus, ou qualquer L&F derivado do Synth.

Na pior das hipoteses, desenhe no JScrollPane e modifique o CellRenderer da JTable para que seja semi-transparente.

As células estão transparentes! :smiley:
O problema é fazer o desenho acompanhar até o final da tabela mesmo sem linhas.
Vou tentar fazer uma nova JTable, se conseguir eu posto aqui!

Só postei esse tópico para ver se alguém tinha pronto, mas valeu!

Rafael,

Quando eu fiz um jogo de xadrez, para colocar a imagem do tabuleiro no fundo da JTable, fiz assim.

[code]JTable tabuleiro = new JTable((TableModel) meuModelo){

   public Component prepareRenderer(tableCellRenderer renderer,int row,int col){
           if(c instanceof JComponent){
            ((JComponent) c).setOpaque(false);
            }
             return c;
   }

   public void paint(Graphics g){
          Image image = new ImageIcon(getClass().resource("/images/tabuleiro.JPG"));
          Dimension d = getSize();
         for(int x = 0; x < d.width; x+=image.getIconWidth()){
                  for(int y = 0; y < d.height; y+=image.getIconHeight()){
                         g.drawImage(image.getImage(),x,y,null,null);
                  }
          }
          super.paint(g);
    }

}[/code]

Jean.Zunino

Desculpe a pergunta, mas que objeto é esse “c” (JComponent) que você referênciou?
É uma JTable? Onde posso encontra-lo?

O código do Jean parece ter sido copiado daqui:

http://www.coderanch.com/t/341744/GUI/java/Jtable-background-image

E o jeito de desenhar a figura parece ter sido resolvido aqui:

http://www.coderanch.com/t/341744/GUI/java/Jtable-background-image#1504278

Veja se isso realmente funciona.

Obviamente você tem de mudar a imagem - esse “http://today.java.net/jag/bio/JagHeadshot.jpg” , que deve ser uma imagem do James Gosling, já é um “dead link” faz algum tempo.

Problema resolvido! :smiley:
Obrigado a todos que ajudaram!
Seguem os códigos:

BIBLIOTECA NECESSÁRIA

packet JTablePlus;

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

/**
 *
 * @author Rafael P. Monteiro
 */
public class CentredBackgroundBorder implements Border  {
     private final ImageIcon image;

     public CentredBackgroundBorder(String sImg) {
         this.image = new ImageIcon(getClass().getResource(sImg));
     }

     public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
         int x0 = x + (width-image.getIconWidth())/2;
         int y0 = y + (height-image.getIconHeight())/2;
         g.drawImage(image.getImage(), x0, y0, null);
     }

     public Insets getBorderInsets(Component c) {
         return new Insets(0,0,0,0);
     }

     public boolean isBorderOpaque() {
         return true;
     }
   
}

CHAMANDO O CÓDIGO

    jScrollPane1.setBackground(Color.BLACK);
    jScrollPane1.getViewport().setOpaque(false);
    final Border bkgrnd = new CentredBackgroundBorder("/imgs/fundo.png");
    Runnable r = new Runnable() {
             public void run() {
                 jScrollPane1.setViewportBorder(bkgrnd);
                 jScrollPane1.repaint();
             }
    };
    SwingUtilities.invokeLater(r);

Utilizei esse código e funcionou, se alguem tentar e não conseguir poste aqui!

OBS: Estou utilizando NetBeans, por isso não coloquei as instânciações de alguns objetos.

1 curtida

De fato, se fizer as coisas direitinho de acordo com o exemplo do Code Ranch, funciona direitinho - mesmo com o Nimbus (só que é preciso ajeitar um pouco o Nimbus porque você acaba perdendo aquela característica de mostrar um fundo zebrado, e a linha corrente fica ressaltada em uma cor inadequada).

rafael_next ,

A classe JComponent é uma classe abstrata onde todos os componentes Swing de extende dela e herdam suas funcionalidades.
Ela se encontra em javax.swing.JComponent.