Background in JDesktopPane without losing quality and expandable

4

I have code to add a background image to a JDesktopPane and it works perfectly on 16:10 widescreen screens. However, when the screen is a bit wider (16: 9), it does not fill the rest of the background. I've seen some other possible ways to do it, but they make the image lose a lot of quality as it just stretches them.

Is it possible to make a middle ground? something that fills when needed , and does not have such significant loss in the image?

package novo;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class TesteJDP extends JFrame {

    private static MeuJDesktopPane jdp = new MeuJDesktopPane();

    public TesteJDP() {
        getContentPane().add(jdp);
        setSize(500, 450);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        TesteJDP teste = new TesteJDP();
        teste.setVisible(true);
    }
}

class MeuJDesktopPane extends JDesktopPane {

    private Image imagem;

    public MeuJDesktopPane() {
        try {
            imagem = new ImageIcon(getClass().getResource("/imagens/fundo.png")).getImage();
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, "Não foi possivel ler a imagem !");

        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Dimension dimension = this.getSize();
        int x = (int) (dimension.getWidth() - imagem.getWidth(this)) / 2;
        int y = (int) (dimension.getHeight() - imagem.getHeight(this)) / 2;
        g.drawImage(imagem, x, y, imagem.getWidth(this), imagem.getHeight(this), this);
    }
}
    
asked by anonymous 16.05.2017 / 14:56

1 answer

3
  

Note: The solution was applied to a JDesktopPane , but since the paintComponent(Graphics g) method is from the JComponent , which is inherited by all swing API components (except some components top-level containers , this solution will probably work for any component of the API.

Based on in this answer in SOEn , you can have the image scaled according to the displayed area of the screen, using BufferedImage .

You first need to create an instance of BufferedImage with the dimensions you want the image to scale:

//dimensoes do componente do qual a imagem servirá de background
Dimension dimension = this.getSize();
int dWidth = (int)dimension.getWidth();
int dHeight = (int)dimension.getHeight();

bi = new BufferedImage(dWidth, dHeight, BufferedImage.TYPE_INT_RGB);

After creating an instance, we need to draw the image with the dimensions informed and, optionally, set some settings to improve the quality. The code has the proper explanations of what each line does:

//cria uma instância de gráficos a partir do BufferedImage
Graphics2D g2 = bi.createGraphics();
//define algumas configurações de interpolação, renderização e antialiasing
//para melhorar um pouco a qualidade da imagem quando for dimensionada
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//renderiza a imagem dentro do BufferedImage
g2.drawImage(imagem, 0, 0, dWidth, dHeight, null);
//com a imagem já desenhada, dispensa essa instância de gráficos
g2.dispose();
//desenha a imagem já dimensionada no componente
g.drawImage(bi, 0, 0, null);

Now just add in the component paintComponent method, not forgetting to check if the image is valid before trying to draw it on the screen:

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);

    BufferedImage bi;

    if (imagem != null) {

        Dimension dimension = this.getSize();
        int dWidth = (int)dimension.getWidth();
        int dHeight = (int)dimension.getHeight();

        bi = new BufferedImage(dWidth, dHeight, BufferedImage.TYPE_INT_RGB);
        //cria uma versao 2D de graficos para que possamos desenhar a imagem na tela
        Graphics2D g2 = bi.createGraphics();
        //define algumas configurações de interpolação, renderização e antialiasing
        //para melhorar um pouco a qualidade da imagem quando for dimensionada
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        //desenha a imagem dentro do BufferedImagem
        g2.drawImage(imagem, 0, 0, dWidth, dHeight, null);
        g2.dispose();
        //finalmente, desenha a imagem já dimensionada no componente
        g.drawImage(bi, 0, 0, null);

    }
}

View the result with an image of 2560x1600 resized to 300x250:

Thesamplecodecanbefound this github link .

    
17.05.2017 / 15:27