简体   繁体   中英

How do I bring JFrame images to the front of my window in Java?

So I'm currently having the problem that a large image will cover up smaller images in my program when i try to graphically display them in Java. I would like to know how to bring certain images to the front of the window so the large "background" image will stay in the background. Also, I do not believe it's a possibility in my program to simply implement the pictures in reverse order.

Here's the code I used: my image manager class with the method I use to implement the images into the window,

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

public class ImageManager extends JFrame {

    private ImageIcon image1;
    private JLabel label1;

    private ImageIcon image2;
    private JLabel label2;

    private ImageIcon image3;
    private JLabel label3;

    public ImageManager() {

    }

    public void addBackground() {
        image3 = new ImageIcon(getClass().getResource("background.png"));
        label3 = new JLabel(image3);
        add(label3);
    }

    public void addSeaweed() {

        image1 = new ImageIcon(getClass().getResource("seaweed.png"));
        label1 = new JLabel(image1);
        add(label1);

    }

    public void addUnderwatervolcano() {
        image2 = new ImageIcon(getClass().getResource("underwatervolcano.png"));
        label2 = new JLabel(image2);
        add(label2);
    }

}

and here's where I use the methods from ImageManager: a method to display a picture of seaweed using the grow() method,

public Seaweed() {

        setLayout(new FlowLayout());
        World.gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        World.gui.setVisible(true);
        World.gui.pack();
        World.gui.setTitle("seaweed and underwatervolcano");
        carbon = 0;
    }


    public void grow() {

        if(World.getOceanCarbon() >= 10) {
            addCarbon(10);
            World.addOceanCarbon(-10);



            World.gui.addSeaweed();
            World.gui.pack();
        }
    }

and heres the method in a different class that uses the grow() method from the Seaweed class and the gui.addBackground() from the ImageManager class,

public static void runWorld() {

        gui.addBackground();

        UnderwaterVolcano volcano = new UnderwaterVolcano();
        Seaweed seaweed = new Seaweed();

        volcano.erupt();
        seaweed.grow();



        gui.setMinimumSize(new Dimension(905, 560));

    }
}

i would like to know how i make it so gui.addBackground() does not cover up the picture of seaweed from gui.addSeaweed() (which was invoked in the seaweed.grow() method) while still invoking gui.addBackground() before invoking gui.addSeaweed(). Is there anyway I can manipulate at the method call the order in which images display in a window? I don't have a very good understanding of JFrame so please be very explanatory with your answers, all help appreciated.

Well your current logic adds all the images to the frame. Swing actually paints the last component added first. That is components are painted based on highest ZOrder being painted first. The default ZOrder of the component is simply the component count at the time the component is added to the panel. So yes based on your current logic the background will paint over top of the other images.

A couple of simple solutions:

1) Manage the ZOrder of your components.

After you add the component to frame you can reset the ZOrder so the component is painted last. So the basic code is

add(aComponent);
setComponentZOrder(aComponent, 0);

2) Add the child images to the background image instead of add all images to the frame. So you have a structure like:

- frame
    - background image
        - seaweed
        - volcano

So the basic logic would be something like:

frame.add( background );
background.add( seaweed );
background.add( volcano );

Since in looks like the seaweed/volcano images are at random places on the background you would still need to manage the size/location of each of these images.

Note when adding child components to the background the child components must be fully contained within the background image or the child image will be truncated.

This is the approach I would use since it better describes the structure of your application. That is your frame contains a background and the background contains other child components. Nesting of components is common to get a desired layout of a frame.

You have to use a LayeredPane. Here is a working example of my own. You only have to replace the used images by some of yours.

The Main class:

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;


public class Main{

    static JFrameWin jFrameWindow;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(runJFrameLater);
    }

    public static class JFrameWin extends JFrame{

        public JFrameWin(){

            // init
            initJFrame(this);

            JPanelSettings jPanelSettings = new JPanelSettings(this.getWidth(), this.getHeight(), this.getX(), this.getY());
            JLayeredPane enclosingJLayeredPane = getEnclosingJLayeredPane(jPanelSettings);

            jPanelSettings = new JPanelSettings(this.getWidth(), this.getHeight(), this.getX(), this.getY(), new File("billard_1.jpg"));
            JPanel backgroundJPanel = getJPanel(jPanelSettings);

            jPanelSettings = new JPanelSettings(this.getWidth()-100, this.getHeight()-100, this.getX()+5, this.getY()+20, new File("billard2.jpg"));
            JPanel firstLayerJPanel = getJPanel(jPanelSettings);

            jPanelSettings = new JPanelSettings(this.getWidth() - 200, this.getHeight() - 200, this.getX() + 60, this.getY() + 60, new File("painter.jpg"));
            JPanel secondLayerJPanel = getJPanel(jPanelSettings);

            // assemble
            enclosingJLayeredPane.add(backgroundJPanel);
            enclosingJLayeredPane.add(firstLayerJPanel);
            enclosingJLayeredPane.add(secondLayerJPanel);

            // adjust layers
            enclosingJLayeredPane.setLayer(backgroundJPanel, 0);
            enclosingJLayeredPane.setLayer(firstLayerJPanel, 1);
            enclosingJLayeredPane.setLayer(secondLayerJPanel, 2);

            // add object to JFrame
            this.add(enclosingJLayeredPane, BorderLayout.CENTER);
        }

    }

    static Runnable runJFrameLater = new Runnable() {
        @Override
        public void run() {
            jFrameWindow = new JFrameWin();
            jFrameWindow.setVisible(true);
        }
    };

    private static void initJFrame(JFrame jFrame) {
        jFrame.setTitle("Boxing Test");
        jFrame.setSize(600, 600);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private static JLayeredPane getEnclosingJLayeredPane(JPanelSettings jPanelSettings){
        JLayeredPane jLayeredPane = new JLayeredPane();
        jLayeredPane.setBounds(jPanelSettings.getXPosition(), jPanelSettings.getYPosition(), jPanelSettings.getWidth(), jPanelSettings.getHeight());
        return jLayeredPane;
    }

    private static JPanel getJPanel(JPanelSettings jPanelSettings){

        BufferedImage bufferedImage = null;

        try {
            bufferedImage = ImageIO.read(jPanelSettings.getImagePath());
        } catch (IOException ex) {
            System.out.println("Error" + ex.toString());
        }

        // fit image to frame size
        Image scaledBufferedImage = bufferedImage.getScaledInstance(jPanelSettings.getWidth(), jPanelSettings.getHeight(), Image.SCALE_DEFAULT);
        JLabel jLabel = new JLabel(new ImageIcon(scaledBufferedImage));

        JPanel jPanel = new JPanel();
        jPanel.setBounds(jPanelSettings.getXPosition(), jPanelSettings.getYPosition(), jPanelSettings.getWidth(), jPanelSettings.getHeight());
        jPanel.add(jLabel);

        return jPanel;
    }

}

A helper-class

import java.io.File;

public class JPanelSettings {

    private int height;
    private int width;
    private int xPosition;
    private int yPosition;
    private File imagePath;

    // Basic constructor
    public JPanelSettings(){ }

    // size and positioning constructor
    public JPanelSettings(int width,int height, int xPosition, int yPosition ){
        setWidth(width);
        setHeight(height);
        setXPosition(xPosition);
        setYPosition(yPosition);
    }

    // Full constructor
    public JPanelSettings(int width,int height, int xPosition, int yPosition, File imagePath ){
        setWidth(width);
        setHeight(height);
        setXPosition(xPosition);
        setYPosition(yPosition);
        setImagePath(imagePath);
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getXPosition() {
        return xPosition;
    }

    public void setXPosition(int xPosition) {
        this.xPosition = xPosition;
    }

    public int getYPosition() {
        return yPosition;
    }

    public void setYPosition(int yPosition) {
        this.yPosition = yPosition;
    }

    public File getImagePath() {
        return imagePath;
    }

    public void setImagePath(File imagePath) {
        this.imagePath = imagePath;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM