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.
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);
}
}
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...