Java - JPanel with background image AND normal fun

2019-05-23 06:09发布

问题:

I've been looking around and working on making a JPanel able to have an image background. I know there is a ton of information reguarding this ( example 1 and example 2 ). Neither of these are exactly what I'm looking for.

What I am looking for, is a way to just add a function or the functionality to set a background image on a JPanel while maintaining everything else. The problem that I have right now is that I have a few classes that extend JPanel and when I change them to extend my new ImagePanel class, the constructor fails (obviously, the parameters are different). I have the constructor for one of those files going super( new BorderLayout() ); and the only way I can get it to function so far is to ditch either the layout, or the background image. I can't get both to work together.

Here's the latest desperate attempt:

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

class ImagePanel extends JPanel {

  private Image img;

  public ImagePanel(Image img, LayoutManager layout) {
    this.img = img;
    Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
    setPreferredSize(size);
    setMinimumSize(size);
    setMaximumSize(size);
    setSize(size);
    setLayout(null);
    super.setLayout(layout);
  }

  public void paintComponent(Graphics g) {
    g.drawImage(img, 0, 0, null);
  }

}

If anyone could help me out, or point me towards what I'm looking for, that would be great. I don't need any super crazy functionality like background scaling or anything like that. I just want an image to be the background, and for it to maintain its functionality in all other ways.

Thanks.

回答1:

If you're open to suggestions, you might consider a JLayeredPane.

These containers have layers, and each layer is capable of storing components.
So, you may have a JPanel, or JLabel for that matter, with your background image on the bottom layer, and place whatever else on another JPanel, in a higher layer.

If you want to stick to your ImagePanel, you probably should call super.paintComponent as well.

class ImagePanel extends JPanel {
        ...

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(img, 0, 0, this);
    }
}


回答2:

Constructors are not transferable between decedents. That is, if you extend a class and don't provide the same constructors as the parent, then you can't use those constructor signatures.

For example, in your sample source code, you couldn't call new ImagePane(new BorderLayout()) as ImagePane doesn't have a constructor matching that signature, despite the fact that JPanel does.

This is important, as it allows you to funnel users to use a specific initialisation path that may be unique to your version of the class.

If you want to re-use the available constructors from the parent class, then you need to provide those signatures within your own class and or call super(...); with the required parameters

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.LayoutManager;
import javax.swing.JPanel;

public class ImagePanel extends JPanel {

    private Image img;

    public ImagePanel(LayoutManager layout) {
        super(layout);
    }

    public ImagePanel(Image img, LayoutManager layout) {
        this(layout);
        this.img = img;
    }

    public Image getImage() {
        return img;
    }

    public void setImage(Image value) {
        if (img != value) {
            Image old = img;
            img = value;
            firePropertyChange("image", old, img);
            revalidate();
        }
    }

    @Override
    public Dimension getPreferredSize() {
        Image img = getImage();
        return img == null ? super.getPreferredSize() : new Dimension(img.getWidth(this), img.getHeight(this));
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (img != null) {
            g.drawImage(img, 0, 0, this);
        }
    }

}

I'd also recommend you take a read through Performing Custom Painting for more details about custom painting...