Java JPanel tiled background image

2020-02-11 06:36发布

问题:

I currently have the code for creating a JOptionPane that tiles an image to the background no matter the size I set it to :)

package test;
import java.awt.*;  
import java.awt.image.BufferedImage;  
import java.io.*;  
import javax.imageio.ImageIO;  
import javax.swing.*;  

public class TiledImage extends JPanel {  
    BufferedImage tileImage;  


    public TiledImage(BufferedImage image) {  
        tileImage = image;  
    }  

    protected void paintComponent(Graphics g) {  
        int width = getWidth();  
        int height = getHeight();  
        for (int x = 0; x < width; x += tileImage.getWidth()) {  
            for (int y = 0; y < height; y += tileImage.getHeight()) {  
                g.drawImage(tileImage, x, y, this);  
            }  
        }  
    }  

    public Dimension getPreferredSize() {  
        return new Dimension(240, 240);  
    }  

    public static void main(String[] args) throws IOException {  
        BufferedImage image = ImageIO.read(new File("./resource/patterngrey.png"));  
        TiledImage test = new TiledImage(image);  
        JOptionPane.showMessageDialog(null, test, "", JOptionPane.PLAIN_MESSAGE);  
    }  
} 

the problem I am having is using the same code to add an image to a JPanel background in a JFrame here is what I have:

package test;
import java.awt.*;  
import java.awt.image.BufferedImage;  
import java.io.*;  
import javax.imageio.ImageIO;  
import javax.swing.*;  

public class TiledImage extends JPanel {  
    BufferedImage tileImage;  
    static JFrame mainFrame = new JFrame("Program Name");
    static JPanel userDetailsPanel = new JPanel();

    public TiledImage(BufferedImage image) {  
        tileImage = image;  
    }  

    protected void paintComponent(Graphics g) {  
        int width = getWidth();  
        int height = getHeight();  
        for (int x = 0; x < width; x += tileImage.getWidth()) {  
            for (int y = 0; y < height; y += tileImage.getHeight()) {  
                g.drawImage(tileImage, x, y, this);  
            }  
        }  
    }  


    public static void main(String[] args) throws IOException {  
        mainFrame.setSize(400,400);
        mainFrame.setLayout(new BorderLayout());
        mainFrame.add(userDetailsPanel, BorderLayout.CENTER);
        BufferedImage image = ImageIO.read(new File("./resource/patterngrey.png"));  
        TiledImage backgroundImage = new TiledImage(image);  
   //   userDetailsPanel.setComponent(backgroundImage); //i know this line is wrong 
   //but i dont know how to correct it
        mainFrame.setVisible(true);
    }  
} 

Any and all help is appreciated if there is a better way of doing it that is a lot less code that would also be great. I do need to add labels and buttons on top of the background once i have my background sorted.

The background needs to be tiled as the application will have a couple of different JPanels in the JFrame with different pattern backgrounds and i would like to make the frame resizable

回答1:

To correct the issue you're currently having, you can set your TiledImage object as the content pane of your JFrame, and then ensure any panels that get added onto it are not opaque.

That is,

public static void main(String[] args) throws IOException {  
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    BufferedImage image = ImageIO.read(new File("./resource/patterngrey.png"));  
    TiledImage backgroundImage = new TiledImage(image);  
    // Make backgroundImage the content pane.
    mainFrame.setContentPane(backgroundImage);
    mainFrame.setLayout(new BorderLayout());
    // Make the userDetailsPanel not opaque.
    userDetailsPanel.setOpaque(false);
    mainFrame.add(userDetailsPanel, BorderLayout.CENTER);

    mainFrame.setSize(400,400);
    mainFrame.setVisible(true);
}  


回答2:

An instance of java.awt.TexturePaint provides a convenient way to tile a BufferedImage. Related examples may be seen here. Given a TexturePaint, you can fill a component's background fairly easily, as shown here.

    private TexturePaint paint;

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setPaint(paint);
        g2d.fillRect(0, 0, getWidth(), getHeight());
    }



回答3:

You state:

Any and all help is appreciated if there is a better way of doing it that is a lot less code that would also be great.

That's not a lot of code actually. The only thing else I could suggest is that if the JPanel is not going to vary in size, create a background BufferedImage, draw your tiled images in that, and then draw the one background image in either your JPanel's paintComponent method, or in a JLabel's icon. If you go the latter route, then give the JLabel a layout manager so that it can act as a well-behaved container for your components. And make sure that anything on top of your tiled containers is not opaque if the image needs to show through, especially JPanels.