Imagem em JPanel

33 respostas
L
Aí, galera... Consegui recuperar uma imagem gravada num campo binário do banco de dados para apresentação num jLabel... O problema é que, quando a imagem se recupera, é apresentada em seu tamanho real, ou seja, as imagens mudam o tamanho do jLabel na área visível do formulário... Já tentei todos os métodos de redimensionamento do jLabel e até redimensionar a imagem, mas sem sucesso... Então pensei que pudesse jogar o array de bytes da imagem direto para um jPanel, como faço com o arquivo de imagem selecionado num JFileChooser... Faço assim... Tenho uma classe extendida de JPanel...
package sigpbones;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;


/**
 *
 * @author lindoélio
 */

public class JImagePanel extends JPanel {
    BufferedImage background = null;
    
    public JImagePanel(BufferedImage img) {
        if (img == null)
            throw new NullPointerException("Sem imagem para processar!");
        this.background = img;
    }
    
    public JImagePanel(File imgSrc) throws IOException {
        this(ImageIO.read(imgSrc));
    }

    public JImagePanel(String fileName) throws IOException {
        this(new File(fileName));
    }
    
    protected void paintComponent(Graphics g) {        
	super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g.create();
        g2d.drawImage(background, 0, 0, this.getWidth(), this.getHeight(), null);
        g2d.dispose();        
    }
}
E então implemento o ActionPerformed do botão de procurar o arquivo de imagem...
private void btnProcurarActionPerformed(java.awt.event.ActionEvent evt) {
    if (fd.showOpenDialog(this) == JFileChooser.CANCEL_OPTION) return;
    try{
        JImagePanel quadroImagem = new JImagePanel(fd.getSelectedFile());  
        painelImagem.add(quadroImagem,BorderLayout.CENTER);
        painelImagem.validate();
    }
    catch (IOException ex) {
        JOptionPane.showMessageDialog(this, "Não foi possível ler a imagem!");
    }
}
E a imagem é então visualizada no painelImagem, respeitando a dimensão do JPanel... Como eu faço para exibir o array de bytes recuperado do banco de dados para um JPanel????

Valeu!!!

33 Respostas

E

Esse array de bytes era uma imgaem em que formato?

Se fosse jpg, imagino que dá pra azer o seguinte:
1-Obter esses bytes.
2-Criar um arquivo temporário (tem um método estático da classe File que faz isso) chamado “imagem.jpg”, por exemplo
3-Escrever esses bytes no arquito temporário acima com algum objeto que escreva array de bytes em arquivos (dá uma olhada em FileWriter, se nãp me engano é esse).
4-sobrescreve o método paintComponent de um JPanel, desenhando este arquivo de imagem…

Teoricamente funciona :wink:

R

Já deu uma olhada no JImagePanel?
http://www.guj.com.br/posts/list/56248.java

L
eclipso:
Esse array de bytes era uma imgaem em que formato?

Se fosse jpg, imagino que dá pra azer o seguinte:
1-Obter esses bytes.
2-Criar um arquivo temporário (tem um método estático da classe File que faz isso) chamado "imagem.jpg", por exemplo
3-Escrever esses bytes no arquito temporário acima com algum objeto que escreva array de bytes em arquivos (dá uma olhada em FileWriter, se nãp me engano é esse).
4-sobrescreve o método paintComponent de um JPanel, desenhando este arquivo de imagem...

Teoricamente funciona ;-)
Fera, vou te explicar o que fiz... Criei um método onde converto as imagens adicionadas através de um JFileChooser (swing) ao JPanel dentro de um JDialog em um array de bytes e gravo esses bytes dentro de um campo do tipo BLOB do banco de dados. Ou seja, tenho um preview, vamos dizer assim, da imagem que selecionei no formulário, onde visualizo a imagem dentro de um JPanel redimensionada ao tamanho dele... O problema é que quando vou visualizar a imagem gravada no banco, recuperando o array de bytes, só consigo jogar essa imagem num JLabel, e o JLabel se redimensiona ao tamanho da imagem ao invés da imagem se redimensionar ao tamanho do JLabel... Então modifiquei meu código para mostrar no JPainel, mas não está funcionando direito... As vezes aparece, se o arquivo for bem pequeno, outras vezes aparesce só um pedacinho... Dá uma olhada no que fiz...
private void recuperarImagem() {
        Image img;
        try {
            conexao.conectar();
            stmt = conexao.con.createStatement();
            rs = stmt.executeQuery("Select Imagem_Log from Logomarcas where Cod_Log = "+codLogo);
            if (rs.next()){  
                img = Toolkit.getDefaultToolkit().createImage(rs.getBytes("Imagem_Log"));
                //labelImagem.setIcon(new javax.swing.ImageIcon(img)); // Mostrava no JLabel...
                
                // Modifiquei aqui para mostrar no JPainel (painelImagem) a imagem resgatada do banco...
                painelImagem.removeAll();
                JImagePanel quadroImagem = new JImagePanel(img);
                painelImagem.add(quadroImagem,BorderLayout.CENTER);
                painelImagem.validate();
            }
            rs.close();
            stmt.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
        finally {
            conexao.desconectar();
        }
    }
Daí, na classe JImagePanel, que já havia criado para visualizar a imagem selecionada através do JFileChooser, alterei o tipo "BufferedImage" para "Image" e ela continuou funcionando aparentemente normal...

Podem me ajudar???

L

Ratao:
Já deu uma olhada no JImagePanel?
http://www.guj.com.br/posts/list/56248.java

Aí, fera…
JImagePanel é uma classe, repassada pelo ViniGodoy, e é exatamente ela que estou implementando…
Sabe me dizer como resolver esse problema implementando essa classe?

Valeu!

I

Tlz te ajude:

Como redimensionar uma imagem

public static ImageIcon redimensionar(Image image, int width, int height, boolean aumentar){
        // Calculos necessários para manter as proporções da imagem, conhecido
        // como "aspect ratio"
        double imageWidth = (double) image.getWidth(null);
        double imageHeight = (double) image.getHeight(null);
        
        double thumbRatio = (double) width / (double) height;
        double imageRatio = imageWidth / imageHeight;
        
        if( imageWidth > width || imageHeight > height || aumentar){
            if (thumbRatio < imageRatio) {
                height = (int) (width / imageRatio);
            } else {
                width = (int) (height * imageRatio);
            }
        }
        else{
            width = image.getWidth(null);
            height = image.getHeight(null);
        }
        
        // Fim do cálculo
        
        BufferedImage thumbImage = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        
        Graphics2D graphics2D = thumbImage.createGraphics();
        
        graphics2D.drawImage(image, 0, 0, width, height, null);
        return (new ImageIcon((Image)thumbImage));
    }
V

Nem precisa de tanta complicação. Existe um segundo drawImage que recebe também o tamanho da imagem de destino, que será desenhada. Use-o.


public abstract boolean drawImage(Image img,
int dx1, int dy1, int dx2, int dy2,
int sx1, int sy1, int sx2, int sy2,
ImageObserver observer)

Em dx1, dy1, dx2, dy você passa as dimensões da imagem de destino, que são as dimensões do painel. Em sx1, sy1, sx2, sy2 você passa as dimensões da imagem original.
Problema resolvido. Você também poderia ter visto isso lá no JImagePanel. Eu disponibilizei o código. :wink:

Um detalhe interessante. Passando os valores de x invertidos você faz um flip horizontal na imagem. Se passar y invertido, faz um flip vertical.

L

ViniGodoy:
Nem precisa de tanta complicação. Existe um segundo drawImage que recebe também o tamanho da imagem de destino, que será desenhada. Use-o.


public abstract boolean drawImage(Image img,
int dx1, int dy1, int dx2, int dy2,
int sx1, int sy1, int sx2, int sy2,
ImageObserver observer)

Em dx1, dy1, dx2, dy você passa as dimensões da imagem de destino, que são as dimensões do painel. Em sx1, sy1, sx2, sy2 você passa as dimensões da imagem original.
Problema resolvido. Você também poderia ter visto isso lá no JImagePanel. Eu disponibilizei o código. :wink:

Um detalhe interessante. Passando os valores de x invertidos você faz um flip horizontal na imagem. Se passar y invertido, faz um flip vertical.


Aí, brother ViniGodoy… Mais uma vez, você!!!
Primeiramente, obrigado pela tamanha disposição em ajudar…
Não entendi direito como fazer isso… Achei num outro post da segunda implementação daquela classe que você repassou no GUJ onde implementou a possibilidade de redimensionar a imagem, centralizar ou repetí-la colocando lado-a-lado…
Será que poderia dizer mais detalhes?
Estou ralando pra conseguir isso…
Consigo visualizar no JPanel quando seleciono a imagem através de um JFileChooser, mas, mesmo usando a mesma classe e métodos não consigo mostrar satisfatoriamente a imagem quando a recupero do banco de dados…
Aguardo… E desde já, grato.
Um abraço!

L

Ah, brother ViniGodoy, aproveitando, para não desviar a discução deste post criei outro perguntando sobre as diferenças do BufferedImage e do Image, porque na classe JImagePanel mudei de BufferedImage para Image afim de conseguir processar a imagem recuperada do banco nesse tipo e continuou funcionando da mesma forma que antes…
Será que tem como você dar uma olhadinha? Ou mesmo me dizer como vou recuperar uma imagem do banco de dados em bytes para o tipo BufferedImage ao invés de Image? Imagino que isso esteja contribuindo para o fracasso nessa operação… Mas só consigo recuperar para o tipo Image com Toolkit…

Image img = Toolkit.getDefaultToolkit().createImage(rs.getBytes("Imagem")); // onde "rs" é o meu ResultSet...
Tentei fazer o casting para BufferedImage, assim:

BufferedImage img = (BufferedImage) Toolkit.getDefaultToolkit().createImage(rs.getBytes("Imagem"));

E quando executo dá erro nessa linha…
Faz idéia???

L
ivo costa:
Tlz te ajude:

Como redimensionar uma imagem

public static ImageIcon redimensionar(Image image, int width, int height, boolean aumentar){
        // Calculos necessários para manter as proporções da imagem, conhecido
        // como "aspect ratio"
        double imageWidth = (double) image.getWidth(null);
        double imageHeight = (double) image.getHeight(null);
        
        double thumbRatio = (double) width / (double) height;
        double imageRatio = imageWidth / imageHeight;
        
        if( imageWidth > width || imageHeight > height || aumentar){
            if (thumbRatio < imageRatio) {
                height = (int) (width / imageRatio);
            } else {
                width = (int) (height * imageRatio);
            }
        }
        else{
            width = image.getWidth(null);
            height = image.getHeight(null);
        }
        
        // Fim do cálculo
        
        BufferedImage thumbImage = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        
        Graphics2D graphics2D = thumbImage.createGraphics();
        
        graphics2D.drawImage(image, 0, 0, width, height, null);
        return (new ImageIcon((Image)thumbImage));
    }
Aí, fera, valeu pela dica!!! Vou testar aqui e ver no que posso aproveitar... Muito obrigado mesmo... Quando implementar volto a dizer no que deu, rsrsr... Um abraço!
V

Qual é a dificuldade?
A área de destino é o painel. Logo, a imagem de destino tem o tamanho do painel.
A área de origem é a própria imagem.

Seu código vai ficar assim:

protected void paintComponent(Graphics g) {           
   super.paintComponent(g);   
   Graphics2D g2d = (Graphics2D)g.create();   
   g2d.drawImage(
      background, 0, 0, getWidth(), getHeight(),  //Tamanho destino = tamanho do painel
      0, 0, background.getWidth(), background.getHeight(), //Tamanho da origem = própria imagem
      null);   
   g2d.dispose();           
}

Me diz uma coisa… como você está fazendo para gravar e recuperar do banco de dados?
Você já conseguiu alguma vez mostrar a imagem corretamente, mesmo em escala natural?

L
Então, brother... A questão das dimensões eu entendi depois de analisar o que tinha me dito e de olhar na documentação que me enviara... Então dei uma mexida e consegui fazer a imagem aparecer... O problema é que só aparece corretamente na primeira vez... Quando eu seleciono outro registro o panel fica piscando a imagem anterior e a nova imagem, como se tivesse dando um refresh muito rápido, e as duas imagens ficam fundidas e piscando, numa confusão geral... Eu consegui gravar como array de bytes em um campo LONGBLOG; o campo BLOB não conseguiu armazenar o array... Eu consigo recuperar a imagem para um JLabel facilmente, mas ela fica em tamanho natural, redimensionando o JLabel... Segue detalhes dos processos de gravar, recuperar e visualizar...
private void incluirLogomarca() {
        try {
            conexao.conectar();
            PreparedStatement pstmt = conexao.con.prepareStatement("+
                                                     "Insert into Logomarcas (Identificacao_Log, Imagem_Log, Observacoes_Log)" +
                                                     "Values (?, ?, ?)");

            ByteArrayOutputStream byteSaida = new ByteArrayOutputStream();
            BufferedImage imagemBuffer = ImageIO.read(new File(editArquivo.getText()));
            ImageIO.write((BufferedImage)imagemBuffer, "jpg", byteSaida);
            byteSaida.flush();
            byte[] byteArray = byteSaida.toByteArray();
            byteSaida.close();
            
            pstmt.setString(1, editIdentificacao.getText());
            pstmt.setBytes(2, byteArray);
            pstmt.setString(3, editObservacoes.getText());
            pstmt.executeUpdate();
            pstmt.close();
        }
        catch (IOException ex) {
            Logger.getLogger(Logomarcas.class.getName()).log(Level.SEVERE, null, ex);
            JOptionPane.showMessageDialog(this, "Não foi possível processar a imagem!");
        }
        catch (SQLException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "Falha na inclusão do registro!\n\nMensagem de erro:\n"+e.getMessage());
        }
        finally {
            conexao.desconectar();
        }
    }
E então o registro é incluído com sucesso... Daí eu recupero o array de bytes do tipo jpg e visualizo...
private void visualizarRegistroSelecionado() {
        Image img = null;
        identLogo = (String) tabelaLogomarcas.getValueAt(tabelaLogomarcas.getSelectedRow(), 0);
        try {
            conexao.conectar();
            stmt = conexao.con.createStatement();
            rs = stmt.executeQuery("Select * from Logomarcas where Identificacao_Log = '"+identLogo+"'");
            if (rs.next()) {
                codLogo = rs.getInt("Cod_Log");
                identLogo = rs.getString("Identificacao_Log");
                obsLogo = rs.getString("Observacoes_Log");
                editIdentificacao.setText(identLogo);
                editObservacoes.setText(obsLogo);

                img = Toolkit.getDefaultToolkit().createImage(rs.getBytes("Imagem_Log"));
                //labelImagem.setIcon(new javax.swing.ImageIcon(img)); // mostrava num JLabel...

                JImagePanel quadroImagem = new JImagePanel(img);
                painelImagem.add(quadroImagem);
                painelImagem.validate();
                // já tentei um monte de métodos por aqui mas sem sucesso...
            }
            rs.close();
            stmt.close();
        }
        catch (SQLException e){
            e.printStackTrace();
        }
        finally {
            conexao.desconectar();
        }
    }
E a classe JImagePanel ficou assim...
public class JImagePanel extends JPanel {
    Image background = null;
    // note que eu tive que mudar de BufferedImage para Image para aceitar a imagem criada pelo Toolkit
    // quando recupero a imagem do array de bytes...

    public JImagePanel(Image img) {
        if (img == null)
            throw new NullPointerException("Sem imagem para processar!");
        this.background = img;
    }
    
    public JImagePanel(File imgSrc) throws IOException {
        this(ImageIO.read(imgSrc));
    }

    public JImagePanel(String fileName) throws IOException {
        this(new File(fileName));
    }
    
    protected void paintComponent(Graphics g) {
	super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g.create();
        g2d.drawImage(background, 0, 0, getWidth(), getHeight(), null);
        g2d.dispose();
        repaint(); // sem esse repaint não aparece nenhuma imagem no panel...
    }
}
Faz ideia??? Aguardo...
L

Ahhh, outro detalhe…
Tentei adicionar as dimensões que você disse

g2d.drawImage(background, 0, 0, getWidth(), getHeight(), 0, 0, background.getWidth(), background.getHeight(), null);

Porém dá erro porque mudei de BufferedImage para Image e pelo o que entendi não deve aceitar mesmo…

V

Estranho, aquele repaint ali dentro do paintComponent está completamente errado. Se você fizer isso, vai fazer com que a imagem fique sendo repintada sempre.
Afinal, o repaint faz com que o swing chame o paintComponent e quando ele chega lá, você força um repaint novamente.

No lugar, chame o método invalidate() só no construtor do seu JImagePanel (e sempre que a imagem for substituída).

V

Quanto ao método de draw, vc pode continuar usando o de assinatura mais simples mesmo. Ele redimensiona a imagem original de acordo com o tamanho que vc passou.
Eu me confundi, o outro é só se vc quiser pegar uma porção da imagem original.

L

Fera, entendi então o porque das imagens ficarem piscando; era por causa do repaint se repetindo no paintComponent()…
No entanto, o problema apenas se modificou…
Sem o repaint() lá dentro a imagem não é visualizada…
Ocorre o seguinte:
Quando recupero a imagem pra visualiza-la não aparece nada no JPanel, daí, quando seleciono outro registro a imagem anterior aparece no JPanel e fica lá… O JPanel não se atualiza mais e fica mostrando sempre a mesma imagem…
Não tem como eu remover a imagem e atualizar o JPanel quando eu quiser???
Fiz assim:

JImagePanel quadroImagem = new JImagePanel(img); painelImagem.add(quadroImagem); painelImagem.repaint();
Tentei painelImagem.remove(quadroImagem);
Tentei painelImagem.removeAll();
Tentei painelImagem.invalidate();
Tentei painelImagem.validate(); antes de repaint, no lugar do repaint, depois do repaint…
Tentei painelImagem.revalidate();
E nada!!!
Caramba, que canseira!!!
O que mais eu posso fazer???

L

Ahhh, outra pergunta…
Você não sabe como eu posso recuperar o array de bytes para um BufferedImage ao invés de Image???
Estou fazendo assim…

Image img = Toolkit.getDefaultToolkit().createImage(rs.getBytes("Imagem_Log"));

Queria obter uma BufferedImage…
Valeu!

V

Use o método ImageIo.read, ao invés do Toolkit. Ele vai ler a imagem como um BufferedImage.
Você chegou a chamar o invalidate() depois que trocou a imagem como eu falei?

L

Cara, não adianta!
Já havia colocado o invalidate()…
Mas tb não funfou…
Não sei como implementar esse ImageIo.read()
Já tentei um monte de parafernalias…
O que eu façoooooooooooooo???
Estou entrando em desespero, kkkkk…

L

Brother, desculpe estar enchendo tanto as paciências, mas dá uma olhada…

BufferedImage imagem = new BufferedImage(painelImagem.getWidth(), painelImagem.getHeight(), BufferedImage.TYPE_INT_RGB); JImagePanel quadroImagem = new JImagePanel(imagem);
Só que no painel aparece tudo preto! Então eu acho que seja porque não passei nenhuma imagem do tipo Image para o “new BufferedImage(…)”, não é mesmo?
Imagina como eu possa passar a imagem que recuperei do banco do tipo Image???

V

Ué, o ImageIO.read funciona estilo o write, mas ao contrário.

BufferedImage img = ImageIO.read(new ByteArrayInputStream(rs.getBytes("Imagem_Log")));

Engraçado com o invalidate não funcionar… Eu sempre fiz assim e funcionou…

V

Outra coisa… estava olhando o seu código ali atrás…

Vc não retira o ImagePanel anterior do painelImagem antes de adicionar um novo ImagePanel?

Faça o seu ImagePanel permitir a modificação da imagem (igual o meu já faz). Então, posicione o ImagePanel apenas uma vez e altere somente a imagem que está dentro dele. Não esqueça de fazer o ImagePanel chamar invalidate a cada troca da imagem.

L

Brother…
Então, será que dá pra você fazer um apanhado de como deveria estar e postar aqui, com base no que eu já te passei???
Já tentei de tudo que eu ví no google, no GUJ e nada…
E valeu por tanta disposição, rsrrsrsrs…

L

ViniGodoy:
Outra coisa… estava olhando o seu código ali atrás…
Vc não retira o ImagePanel anterior do painelImagem antes de adicionar um novo ImagePanel?
Faça o seu ImagePanel permitir a modificação da imagem (igual o meu já faz). Então, posicione o ImagePanel apenas uma vez e altere somente a imagem que está dentro dele. Não esqueça de fazer o ImagePanel chamar invalidate a cada troca da imagem.

Cara, como assim?
Não entendi!!!

V

Você está dando add num novo JImagePanel.
Mas, na segunda vez que você selecionar uma imagem, já vai ter um JImagePanel lá!!!

O que você faz com ele?

O que eu falei é fazer com que o seu JImagePanel suporte o método setImage. Assim, você adiciona o JImagePanel no painelImagem uma única vez.
E toda vez que carregar uma imagem do banco só chama o método setImage.

L

Bom, vamos ver se entendi…
Quer dizer que quando eu implemento JImagePanel quadroImagem = new JImagePanel(img) e então painelImage.add(quadroImagem) eu não preciso fazer isso novamente para mostrar outra imagem???
Então posso fazer isso no construtor do formulário e apenas modificar a imagem com setImage???
Você disse que eu devo fazer como você já fez com a classe JImagePanel, mas eu sou inexperiente ainda, e você é fera, então não tem como você postar sua classe JImagePanel para eu me basear???

V

O ratao já postou o link, logo no início dessa thread:
http://www.guj.com.br/posts/list/56248.java#295271

L
Aí, brother ViniGodoy!!!!!!!!!!!!! Consegui!!! Ufaaaaa!!! Estou muito agradecido pelas dicas... Foram muito úteis! Então segue a maneira como consegui para quem passar pelo mesmo problema... Adicionei a classe JImagePanel com a implementação dos demais métodos...
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.TexturePaint;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class JImagePanel extends JPanel {
    private BufferedImage image = null;
    private FillType fillType = FillType.RESIZE;

    public JImagePanel(BufferedImage img) {
        setImage(img);
    }
    
    public JImagePanel(File imgSrc) throws IOException {
        this(ImageIO.read(imgSrc));
    }

    public JImagePanel(String fileName) throws IOException {
        this(new File(fileName));
    }

    public final void setImage(BufferedImage img) {
        if (img == null)
            throw new NullPointerException("Sem imagem para processar!");
        this.image = img;
        invalidate();
    }

    public void setImage(File img) throws IOException {
        setImage(ImageIO.read(img));
    }

    public void setImage(String fileName) throws IOException {
        setImage(new File(fileName));
    }

    public BufferedImage getImage() {
        return image;
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        fillType.drawImage(this, g2d, image);        
        g2d.dispose();
    }

    public FillType getFillType() {
        return fillType;
    }

    public void setFillType(FillType fillType) {
        if (fillType == null)
            throw new IllegalArgumentException("Invalid fill type!");
        this.fillType = fillType;
        invalidate();
    }

    public static enum FillType {
        RESIZE {
            public void drawImage(JPanel panel, Graphics2D g2d, BufferedImage image) {
                g2d.drawImage(image, 0, 0, panel.getWidth(), panel.getHeight(),
                        null);
            }
        },
        
        CENTER {
            public void drawImage(JPanel panel, Graphics2D g2d, BufferedImage image) {
                int left = (panel.getHeight() - image.getHeight()) / 2;
                int top = (panel.getWidth() - image.getWidth()) / 2;
                g2d.drawImage(image, top, left, null);
            }
        },

        SIDE_BY_SIDE {
            public void drawImage(JPanel panel, Graphics2D g2d, BufferedImage image) {
                Paint p = new TexturePaint(image, new Rectangle2D.Float(0, 0, image.getWidth(), image.getHeight()));
                g2d.setPaint(p);
                g2d.fillRect(0, 0, panel.getWidth(), panel.getHeight());
            }
        };
        public abstract void drawImage(JPanel panel, Graphics2D g2d, BufferedImage image);
    }
}
Depois, instanciei um "quadroImagem" logo no início da classe onde quero visualizar as imagens resgatadas do banco...
private JImagePanel quadroImagem = null;
E então resgato a imagem adicionando-a ao quadroImagem e o quadroImagem ao JPanel, toda vez que precisar mudar a imagem. Note que não foi necessário retirar o quadroImagem para adicionar outra imagem devido ao bem pensado método "setImage()"... Outro ponto positivo que encherguei foi o resgate dos bytes para uma BufferedImage sem a utilização de codecs, como alguns fazem, pois assim eu consegui visualizar com esse mesmo código imagens do tipo jpg, png e gif (que foram as que testei)...
ResultSet rs = stmt.executeQuery("Select Imagem_Log from Logomarcas where Identificacao_Log = '"+identLogo+"'");
    if (rs.next()) {
        BufferedImage img = ImageIO.read(new ByteArrayInputStream(rs.getBytes("Imagem_Log")));
        if (quadroImagem == null) quadroImagem = new JImagePanel(img);
        quadroImagem.setImage(img);
        painelImagem.add(quadroImagem);
        painelImagem.repaint();
    }
    rs.close();
Agora preciso apenas redimensionar a imagem ao tamanho do JPanel mantendo o aspect ratio da imagem, porque o redimensionar dessa classe altera tanto a altura quanto a largura para as dimensões exatas do JPanel... Se souber como vou fazer isso, agradeceria... Um abraço!
L
Hehehehehehehhehehe... Consegui, ViniGodoy!!!!!!!!!!!! Botei a cuca pra funcionar aqui para uns cálculos e consegui adicionar duas funcionalidades na classe JImagePanel... Bem simples, porém muito útil, pelo menos para a minha aplicação... O RESIZE da classe JImagePanel redimensiona tanto a altura da imagem quanto a largura à área total do JPanel, sendo assim, se a dimensão da imagem for 600 x 300 e a do JPanel for 200 x 200 a imagem será então esticada pra preencher todo o JPanel, e isso é um problema se você precisa visualizar as dimensões reais da imagem... Acho que a solução para isso se chama Aspect Ratio; por isso criei duas funções com esse nome para a classe JImagePanel; uma, a ASPECT_RATIO, calcula as dimensões fieis da imagem referentes à largura ou altura do JPanel e visualiza na posição padrão (eixo 0,0; portanto, à esquerda); a outra, a ASPECT_RATIO_CENTER faz o mesmo calculo da primeira mas centraliza a imagem no JPanel obtendo o eixo X,Y da comparação entre os aspectos... Para mim vai ser muito útil, e queria contribuir pela disposição em me ajudar... Olha o que acrescentei...
ASPECT_RATIO {
            public void drawImage(JPanel panel, Graphics2D g2d, BufferedImage image) {
                int larguraImg = image.getWidth(), alturaImg = image.getHeight();
                int largura = 0, altura = 0;
                double aspectoImg = larguraImg / alturaImg;
                double aspectoPanel = panel.getWidth() / panel.getHeight();
                
                if (larguraImg > panel.getWidth() || alturaImg > panel.getHeight()) {
                    if (aspectoImg == aspectoPanel) {
                        largura = panel.getWidth();
                        altura = panel.getHeight();
                    }
                    if (aspectoImg != aspectoPanel) {
                        if ((larguraImg / panel.getWidth()) > (alturaImg / panel.getHeight())) {
                            largura = panel.getWidth();
                            altura = (largura * alturaImg) / larguraImg;
                        }
                        if ((larguraImg / panel.getWidth()) < (alturaImg / panel.getHeight())) {
                            altura = panel.getHeight();
                            largura = (altura * larguraImg) / alturaImg;
                        }
                    }
                }
                else {
                    largura = image.getWidth();
                    altura = image.getHeight();
                }
                g2d.drawImage(image, 0, 0, largura, altura, null);
            }
        },
        
        ASPECT_RATIO_CENTER {
            public void drawImage(JPanel panel, Graphics2D g2d, BufferedImage image) {
                int larguraImg = image.getWidth(), alturaImg = image.getHeight();
                int largura = 0, altura = 0;
                double aspectoImg = larguraImg / alturaImg;
                double aspectoPanel = panel.getWidth() / panel.getHeight();
                
                if (larguraImg > panel.getWidth() || alturaImg > panel.getHeight()) {
                    if (aspectoImg == aspectoPanel) {
                        largura = panel.getWidth();
                        altura = panel.getHeight();
                    }
                    if (aspectoImg != aspectoPanel) {
                        if ((larguraImg / panel.getWidth()) > (alturaImg / panel.getHeight())) {
                            largura = panel.getWidth();
                            altura = (largura * alturaImg) / larguraImg;
                        }
                        if ((larguraImg / panel.getWidth()) < (alturaImg / panel.getHeight())) {
                            altura = panel.getHeight();
                            largura = (altura * larguraImg) / alturaImg;
                        }
                    }
                }
                else {
                    largura = image.getWidth();
                    altura = image.getHeight();
                }
                
                // centraliza a imagem no JPanel...
                int left = (panel.getHeight() - altura) / 2;
                int top = (panel.getWidth() - largura) / 2;
                
                g2d.drawImage(image, top, left, largura, altura, null);
            }
        };
Um grande abraço! Até que enfim posso finalizar esse post, rsrsrsrsrs... Valeuuuuuuuuuu!!!
V

Legal, parabéns! :slight_smile:

L
Heheheh... Olha eu aqui de novo, rsrsrsrs... Só quero corrigir um erro no calculo do ASPECT_RATIO... É preciso fazer o casting das dimensões para double antes da comparação, pois em algumas imagens a aspecto não era respeitado pelas dimenões estarem arredondadas ou truncads para inteiro... E então só precisava comparar os aspectos... Agora, o cálculo correto...
ASPECT_RATIO {
            public void drawImage(JPanel panel, Graphics2D g2d, BufferedImage image) {
                int larguraImg = image.getWidth(), alturaImg = image.getHeight();
                int largura = 0, altura = 0;
                double aspectoImg = (double) larguraImg / (double) alturaImg;
                double aspectoPanel = (double) panel.getWidth() / (double) panel.getHeight();
                
                if (larguraImg > panel.getWidth() || alturaImg > panel.getHeight()) {
                    if (aspectoImg == aspectoPanel) {
                        largura = panel.getWidth();
                        altura = panel.getHeight();
                    }
                    if (aspectoImg > aspectoPanel) {
                        largura = panel.getWidth();
                        altura = (largura * alturaImg) / larguraImg;
                    }
                    if (aspectoImg < aspectoPanel) {
                        altura = panel.getHeight();
                        largura = (altura * larguraImg) / alturaImg;
                    }
                }
                else {
                    largura = image.getWidth();
                    altura = image.getHeight();
                }
                g2d.drawImage(image, 0, 0, largura, altura, null);
            }
        },
        
        ASPECT_RATIO_CENTER {
            public void drawImage(JPanel panel, Graphics2D g2d, BufferedImage image) {
                int larguraImg = image.getWidth(), alturaImg = image.getHeight();
                int largura = 0, altura = 0;
                double aspectoImg = (double) larguraImg / (double) alturaImg;
                double aspectoPanel = (double) panel.getWidth() / (double) panel.getHeight();
                
                if (larguraImg > panel.getWidth() || alturaImg > panel.getHeight()) {
                    if (aspectoImg == aspectoPanel) {
                        largura = panel.getWidth();
                        altura = panel.getHeight();
                    }
                    if (aspectoImg > aspectoPanel) {
                        largura = panel.getWidth();
                        altura = (largura * alturaImg) / larguraImg;
                    }
                    if (aspectoImg < aspectoPanel) {
                        altura = panel.getHeight();
                        largura = (altura * larguraImg) / alturaImg;
                    }
                }
                else {
                    largura = image.getWidth();
                    altura = image.getHeight();
                }
                
                // centraliza a imagem no JPanel...
                int left = (panel.getHeight() - altura) / 2;
                int top = (panel.getWidth() - largura) / 2;
                
                g2d.drawImage(image, top, left, largura, altura, null);
            }
        };
Um abraço!
L

Aí, ViniGodoy, desculpe estar voltado nesse post, mas tenho uma nova empreitada para realizar relacionado a esse assunto…
Preciso adicionar uma image ao JPanel fazendo com que ele a pinte por cima da imagem já pintada, não apagando-a…
Ou, caso seja possível com BufferedImage, preciso pintar determinadas partes da imagem com cores diferentes…
Para não delongar este post criei um novo, específico para o meu problema…
Ficaria muito agradecido se me ajudasse novamente, porque imagino que você domine isso também…
O post é esse aí: http://www.guj.com.br/posts/list/96709.java#519240
Valeu!

H

Ja tentei de tudo e a imagem nao fica no panel
O maximo que consegui foi fazer ela aparecer e sumir bem rapido, isso depois da segunda tentativa na escolha de arquivo
Grava na Base tranquilo, mas nao aparece no Jpanel
acredito que recupera da base tambem, porque não da erro, mas não aparece no panel
ja tentei jlabel, jpanel, haa, ela chega a piscar com draw
ja tentei ajustando o metodo abaixo ai e nada:

public class JMeuPainel extends JPanel
{

Image im = new ImageIcon ( getClass ( ).getResource ( "/fundo.png" ) ).getImage ( );   

public void paintComponent ( Graphics g )   
{   
    super.paintComponent ( g );   
    int x = ( this.getWidth ( ) - im.getWidth ( null ) ) / 2;   
    int y = ( this.getHeight ( ) - im.getHeight ( null ) ) / 2;   
    g.drawImage ( im , x , y , this );   
}

}
Oque eu faço para ela aparecer e permanecer na tela, não me importa o componente
Como que na pre visualização do JFileChoose a mardita fica la, bonitinha
:frowning:

L

Fera, invoque o método invalidate() sempre que for reescrever o método paintComponent() do JPanel, e adicione o método validate() e um repaint() logo depois do método paintComponent(), para o conteúdo ser repintado no JPanel…
Porque você não fez exatamente como eu fiz, numa classse separada, com os métodos para tratar a imagem separadamente?
Tentar simplificar, nesse caso, só piora, rsrsrsr!
Se quiser fazer como eu fiz e não entender pode perguntar que te explico parte por parte…
Um abraço!

Criado 3 de julho de 2008
Ultima resposta 19 de jul. de 2008
Respostas 33
Participantes 6