Ich habe ein JFrame mit einem BorderLayout.
Am Ende des JFrames habe ich ein JPanel platziert auf diesem befinden sich ein paar buttons.
Nun möchte ich ein Hintergrundbild auf dem Jpanel setzen, was aber nicht so einfach funktioniert.
Daher dachte ich mir, ich setze auf das JPanel ein JLayeredPane mit zwei ebenen (new Integer(0) & new integer(1)). Auf 0 habe ich ein JLabel das mit einem Bild bestückt wird und auf 1 werden die Buttons dargestellt.
Nun werden die Buttons angezeigt nur das JLabel zeigt kein Bild an.
Pfad zum Bild passen und die programmierung auch.
Nun Frage ich mich, ob das prinzipiel überhaupt so funktionieren kann?
JFrame mit JLayeredPane und JPanel funktioniert, habe ich schon gemacht, nur JFrame mit JPanel & JLayeredPane??
Hier mal ein vollständiges Beispiel eines JFrames mit einem JPanel, das ein Hintergrundbild zeichnen kann. In einem weiteren JPanel werden ein paar Dummy-Buttons angezeigt.
Lies dir die Anmerkungen durch, spiele etwas mit dem Code an den beschriebenen Stellen und sieh, wie sich das Programm verhält.
import java.awt.*;
import javax.swing.*;
import javax.imageio.*;
import java.io.*;
import java.net.*;
public class BackgroundImageTest {
public BackgroundImageTest() {
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
JFrame frame = new JFrame("BackgroundImage-Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(createMainPanel());
frame.setSize(size.width * 70 / 100, size.height * 70 / 100);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JPanel createMainPanel() {
Image image = null;
String url = "http://hintergrundbild.org/wallpaper/full/b/d/7/43686-beautiful-hintergrundbilder-fuer-samsung-tablet-1920x1080-fuer-android-40.jpg";
try {
image = ImageIO.read(new URL(url));
} catch(IOException ioe) {
JOptionPane.showMessageDialog(null,
"Das Hintergrundbild konnte nicht geladen werden!\n" + ioe.getLocalizedMessage(),
ioe.getClass().getName(),
JOptionPane.WARNING_MESSAGE);
}
BackgroundImagePanel mainPanel = new BackgroundImagePanel(new BorderLayout());
mainPanel.setImage(image); //hier kann man einstellen, ob das Bild im Original oder eingepasst ausgegeben werden soll (true/false)
JPanel southPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
southPanel.setOpaque(false); //entscheidet, ob das Button-Panel durchsichtig sein soll
southPanel.add(createButtonPanel(southPanel.isOpaque()));
mainPanel.add(southPanel, BorderLayout.SOUTH);
return mainPanel;
}
//erzeugt ein Panel mit Buttons, bei Übergabe von true wird das Panel undurchsichtig
private JPanel createButtonPanel(boolean opaque) {
JPanel panel = new JPanel(new GridLayout(1, 0, 5, 5));
panel.setOpaque(opaque);
panel.add(new JButton("Abbrechen"));
panel.add(new JButton("OK"));
//Ereignisverarbeitung fehlt!
return panel;
}
class BackgroundImagePanel extends JPanel {
private Image image;
private boolean fitImage;
BackgroundImagePanel() {
super();
}
BackgroundImagePanel(LayoutManager layout) {
super(layout);
}
/**
* Nimmt das zu zeichnende Bild entgegen und nimmt Einstellungen vor, die das Hintergrundbild im Originalformat
* und in den Original-Dimensionen ausgeben werden.
*
* @param image das zu zeichnende Bild
*/
void setImage(Image image) {
this.setImage(image, false);
}
/**
* Nimmt das zu zeichnende Bild entgegen und nimmt Einstellungen vor, die das Hintergrundbild im Originalformat
* und und in den Original-Dimensionen oder in Format und Dimension des Panels ausgeben werden.
*
* @param image das zu zeichnende Bild
* @param fitImage bei Übergabe von true wird das Bild immer an die Größe des Panel angepasst (kann zu Verzerrung führen),
* ansonsten wird immer das Original gezeichnet.
*/
void setImage(Image image, boolean fitImage) {
this.image = image;
this.fitImage = fitImage;
validate();
repaint();
}
/**
* @see javax.swing.JComponent#getPreferredSize()
*/
@Override
public Dimension getPreferredSize() {
if(image != null) {
System.out.println(this.getSize());
return new Dimension(image.getWidth(this), image.getHeight(this));
}
return super.getPreferredSize();
}
@Override
protected void paintComponent(Graphics g) {
if(image != null) {
if(fitImage) {
Dimension size = this.getSize();
g.drawImage(image, 0, 0, size.width, size.height, this);
} else {
g.drawImage(image, 0, 0, this);
}
}
}
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(Exception e) {
System.err.println(e);
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new BackgroundImageTest();
}
});
}
}
Leider tut das Programm bei mir gar nichts. Es öffnet sich kein Fenster, es kommt auch keine Meldung, nur das rote Quadrat von Eclipse zeigt an, dass es läuft.
Bei mir geht’s auch. Kann es sein, dass er bei einer seeeehr langsamen Netzverbindung (oder wenn er hinter irgendeiner Firmenproxywall hängt) ein Problem mit dem Bild hat? Ggf. mal ein lokales JPG versuchen - ist aber nur wild geraten, eigentlich sieht sonst im Code alles OK aus…
Ja daran wird es liegen, während ich gestern nichts bekam, war da heute immerhin ein Kasten mit “Das Hintergrundbild kann nicht geladen werden! Can’t get input stram from URL!” und dem Titel “javax.imageio.IIOE.exception”.