Swing setContentPane verdeckt mir alle Buttons Labels etc...

xJan45x

Aktives Mitglied
Hallo,
Ich habe ein kleines Problem und einfach keine Lösung gefunden. Und zwar habe ich ein JFrame und habe mir ein Hintergrund Bild erstellt und ich wollte das gerne wenn man das Bild groß macht das der Hintergrund auch mit Groß wird Das Habe ich auch hinbekommen. Aber meine ganzen JButtons, JLabels, JCheckBoxs sind jetzt alle hinter dem HintergrundBild und ich will sie gerne vor dem Bild haben. Wenn ich den Hintergrund mit ein JLabel mache dann passt sich das Bild nicht an wenn man es groß macht. Deswegen habe ich setContentPane() genommen. Das Bild wir auch angezeigt aber wie gesagt meine ganzen Compomenten sind halt hinter dem Bild und ich möchte sie gerne davor haben.
Wie kann ich das machen?
 
Mit setContentPane() werden deine Buttons nicht verdeckt sondern sie werden einfach nicht mehr angezeigt.
Guck dir mal den ComponentListener an.

Du erweiterst ein JLabel, lässt es ComponentListener erweitern, fügst es zum JFrame als ComponentListener hinzu und überschreibst die ComponentRezized() Methode im erweiterten JLabel. In diese Methode schreibst du die Anpassung an die veränderte Größe des JFrames.

Also in Code:

Java:
public class HintergrundLabel extends JLabel implements ComponentListener{

 @Override
 public void componentRezized(ComponentEvent e){
  Rectangle frameRect = e.getComponent().getBounds();
  int höhe = frameRect.getHeight();
  int breite = frameRect.getWidth();
  //Mach deine Anpassungen
 }
}

und zum Frame fügst du das Label mit
Java:
frame.addComponentListener(new HintergrundLabel());
hinzu.
 
Zuletzt bearbeitet:
Bei mir wird das Hintergrund Bild nicht angezeigt. Ich habe eine Klasse erstellt die "SingelPlayerCompmentenListener" heißt. In der Klasse habe ich dann hingeschreiben "extends JLabel implements ComponentListener" hinter denn Klassen namen. Dann habe ich die Methoden implementiert und habe in der Methode "componentResized" Folgenes rein geschrieben:
Java:
	@Override
	public void componentResized(ComponentEvent e) {
		Rectangle frameRect = e.getComponent().getBounds();
		int höhe = (int) frameRect.getHeight();
		int breite = (int) frameRect.getWidth();
		setSize(breite, höhe);
		try {
			setIcon(new ImageIcon(ImageIO.read(getClass().getResource("background.png"))));
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
Und bei mein JFrame habe ich dieses hingeschreiben:
Java:
	addComponentListener(new SingelPlayerCompmentenListener());
Aber wenn ich die Anwendung Starte habe ich einfach nur ein weißen Hintergrund. Die Datei "background.png" ist vorhanden!
Aber warum wird mir mein Hintergrund Bild nicht angezeigt habe ich was falsch gemacht? Falls ja was?
 
Du lädst das Icon jedes Mal neu. Es ist besser, wenn du es ein mal einließt und dann im Speicher behältst. Die Festplatte ist im Gegensatz zum Rest extrem langsam.

Der Code von mir war nur ein Beispiel. Du musst das JLabel natürlich trotzdem zu deinem ContentPane hinzufügen. 😉
 
Wie kann ich das Image Speichern?
Muss ich das JLabel dann ganz normal wieder hinzufügen als wenn es ein normales JLabel(Also setSize, frame.add())?
Oder wie?
 
Zuletzt bearbeitet:
In einer Variable vom Typ ImageIcon. So schwer ist das nicht. 😉

Ja. So wäre das. Du fügst es so hinzu, dass es anfangs framefüllend ist. Alle weiteren Anpassungen an veränderte Größen nimmst du in componentResized(...) vor.



Noch eine Sache: Man bennent Klassen nicht nach dem Interface, dass sie implementieren sondern nach der Aufgabe, die sie erfüllen. Dein JLabel hieße also z. B. HintergrundJLabel 😉
 
Also speichere ich das Bild im ImageIcon dann lade ich es beim aufrufen des Consturtors. Und wenn ich das Bild maxiemiere also componentResized(...) Event setzte ich einfach die Size vom Label auf die neue Größe mit Height und Width? Und dann bei mein Frame repaint() aufrufen richtig?
Und halt noch dann ganz normal adden zum frame wie ein normales JLabel und den Listener adden
 
Zuletzt bearbeitet:
Das mit dem ImageIcon sähe so aus:
Java:
public class Hinterlabel extends...{
 private ImageIcon hintergrund;

 public Hinterlabel(...){
  hintergrund = ImageIO.....;
 }
}

Das du die Größe anpasst stimmt. Nur vermutlich müsstest du auch die Größe des Icons anpassen.
Wozu brauchst du denn JFrame.repaint()?

Das Hinzufügen stimmt.
 
Bei mir sieht die Klasse jetzt so aus
Java:
public class BackgroundJLabel extends JLabel implements ComponentListener{

	private static final long serialVersionUID = 5627376614400938558L;
	private ImageIcon icon = null;
	
	public BackgroundJLabel() {
		try {
			icon = new ImageIcon(ImageIO.read(getClass().getResource("bg.png")));
		} catch (IOException e) {
			e.printStackTrace();
		}
		setIcon(icon);
	}
	
	@Override
	public void componentResized(ComponentEvent e) {
		Rectangle frameRect = e.getComponent().getBounds();
		int höhe = (int) frameRect.getHeight();
		int breite = (int) frameRect.getWidth();
		int x = (int) frameRect.getX();
		int y = (int) frameRect.getY();
		setBounds(x, y, breite, höhe);
		setIcon(icon);
	}

	@Override
	public void componentMoved(ComponentEvent e) {}

	@Override
	public void componentShown(ComponentEvent e) {}

	@Override
	public void componentHidden(ComponentEvent e) {}


}

Und benutzen tut ich das ganz so:
Java:
	private JLabel bglabel;
		bglabel = new BackgroundJLabel();
		add(bglabel);
		addComponentListener(new BackgroundJLabel());
Also ich habe in der Klasse extends JFrame drin stehen. Aber mein Hintergrund ist immer nur dann Weis Warum?
 
Du musst bglabel als ComponentListener hinzufügen und kein neues Label sonst klappt das nicht.

Und, sofern du nicht mit einem LayoutManager arbeitest, musst du bglabel einw Größe mitgeben.
 
Zuletzt bearbeitet:
Also ich weis nicht was ich da falsch mache ich habe jetzt einfach addComponentListener(new BackgroundLabel()); gemacht aber es geht immer noch. Wie man mit denn LayoutManager arbeitet weis ich nicht genau
 
Du erzeugst eine neue Instanz von BackgroundLabel und fügst diese als Listener hinzu und vorher erzeugst du eine Instanz und fügst diese zum ContentPane hinzu. Du hast also insgesamt zwei Instanzen. Du musst aber beide Male DASSELBE HintergrundPanel hinzufügen.
 
Nochmal zu deinem ursprünglichen Problem: Du willst ein Programm machen, dass aus einem JFrame besteht. Dabei möchtest du ein Bild als Hintergrund einfügen, ohne dabei die anderen Komponenten zu verdecken. Ich habe schon mal ein solches Programm geschrieben und dabei habe ich einfach ein JLabel als ContentPane des JFrames benutzt:

Code:
frame.setContentPane(new JLabel());

Diesem JLabel habe ich ein ImageIcon gegen (für den Hintergrund halt). Aber genug geredet, hier mal die gesamte Klasse:

Java:
package XXX.XXX.XXX;

import java.awt.FlowLayout;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class FensterMitHintergrund extends JFrame {
	
	public FensterMitHintergrund() {
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(500, 500);
		setLocationRelativeTo(null);
		setContentPane(new JLabel(new ImageIcon("PFAD/ZUM/HINTERGRUNDBILD.png"))); 
		FlowLayout layout = new FlowLayout();
		getContentPane().setLayout(layout);
		getContentPane().add(new JButton("Ich bin ein JButton"));
	}

	public static void main(String[] args) {
		FensterMitHintergrund window = new FensterMitHintergrund(); 
		window.setVisible(true);
	}	
}

Diese Klasse erzeugt beim Starten ein JFrame-Objekt mit einem Hintergrundbild (falls der Pfad gültig ist und das Bild existiert). Außerdem wird ein JButton dem ContentPane hinzugefügt, welches problemlos im Vordergrund gezeichnet wird.
Ich rate dir sehr, dass du das NimbusLookAndFeel benutzt, da die Ränder von bspw. JButtons sonst weiß werden.

MfG Mika
 
Zuletzt bearbeitet:
ich würde einfach das von dir gewünschte bild in einem JPanel realisieren, und diesen dann einfach als ContentPane für deinen Frame verwenden ,

alle anderen Komponenten weißt du dann über das Borderlayout des JFrames die dementsprechende Position zu .

Hier ein Beispiel ( alle Komponenten werden 'automatisch' ÜBER deinem Hintergrundbild angeordnet ):

Das ImagePane ist so umgesetzt, das es automatisch die Größe deiner Grafik annimmt, und ein aufruf von pack() der klasse JFrame in der Klasse Main.java sorgt dafür das der Frame so groß wird wie der inhalt seiner contentPane.

ImagePane.java
Java:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;


@SuppressWarnings("serial")
public class ImagePane extends JPanel{

	private BufferedImage image;
	
	public ImagePane(String file){
		loadImage(file);
		init();
	}
	
	private void loadImage(String file){
		try {
			image = ImageIO.read(new File(file));
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void init(){
		setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
	}
	
	@Override
	public void paintComponent(Graphics g){
		super.paintComponent(g);
		
		g.drawImage(image, 0, 0, null);	
	}
	
	public BufferedImage getImage()				{return image;}
}


EDIT :

falls du das Image als resource laden möchtest ( also das Bild in einem Ordner , innerhalb deiner Projektstruktur liegen sollte ), kannst du dies mit

Java:
try{
  image = ImageIO.read(getClass().getResourceAsStream(file);
catch(IOException e){
  e.printStrackTrace();
}
}

machen.

Main.java
Java:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;


public class Main{

	public static void main(String[] args){
		JFrame f = new JFrame("Mein Frame");
		f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		
		
//		Hintergrund setzen ( automatisch ist der Frame so groß wie das Bild )
		f.setContentPane(new ImagePane("F:/Bilder/Wallpaper/1.jpg"));
		
//		Beliebige Komponenten hinzufügen 
		f.add(BorderLayout.PAGE_START, new JLabel("Ich bin ein tolles JLabel"));
		
		f.pack();
		f.setLocationRelativeTo(null);
		f.setVisible(true);
	}
}

oder du gehst den Weg den Gucky dir bereits beschrieben hatte.

Den Weg zu wählen und von JFrame abzuleiten würde ich eher nicht empfehlen.
 
Zuletzt bearbeitet:

Zurück
Oben