# JFrame mit background bild -> verschiebt Buttons ?



## Guest (25. Jan 2008)

Hey, und zwar werden die Buttons dort gesetzt, wo ich sie hinsetze, wenn ich


```
main.setContentPane(new BackGroundPane("menu.jpg"));
```

nicht aufrufe. Und wenn ich es aufrufe, dann reihen die sich einfach nebeneinander, und
platzieren sich nicht dort, wo sie sollen.

Was hat das Hintergrundbild damit zu tun? Ich muss dazu sagen, dass ich totaler Anfänger bin und den Code für 
das Hintergrundbild, also die Klasse mit allem, einfach aus einem Forumsbeitrag kopiert habe

(Es funktioniert auch, aber es verschiebt eben die Buttons)


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

public class Game{
	
	public static void main(String[] args){
		
		/* create the window */
		JFrame main = new JFrame("mein Frame");
		main.setLayout(null);
		main.setSize(1024,768);
		main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		main.setLocation(
        (Toolkit.getDefaultToolkit().getScreenSize().width-
         main.getSize().width) / 2,
        (Toolkit.getDefaultToolkit().getScreenSize().height-
         main.getSize().height) / 2); 
         
        /* set background picture for window */
        main.setContentPane(new BackGroundPane("menu.jpg"));
		
		/* create buttons */
		AbstractButton startGame = new JButton();
		startGame.setIcon(new ImageIcon( "icon/startGame.jpg" ));
		startGame.setBounds(20,80,420,220);
		
		AbstractButton showStats = new JButton();
		showStats.setIcon(new ImageIcon( "icon/showStats.jpg" ));
		showStats.setBounds(20,320,420,220);
		
		AbstractButton exit = new JButton();
		exit.setIcon(new ImageIcon( "icon/exit.jpg" ));
		exit.setBounds(946,680,50,50);
		
		/* create button rollover help text */
		
		
		/* add and display */
		main.add(startGame);
		main.add(showStats);
		main.add(exit);
		main.setVisible(true);
	}
}

class BackGroundPane extends JPanel{
		Image img = null;

		BackGroundPane(String imagefile) {
			if (imagefile != null) {
				MediaTracker mt = new MediaTracker(this);
				img = Toolkit.getDefaultToolkit().getImage(imagefile);
				mt.addImage(img, 0);
				try {
					mt.waitForAll();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}

		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.drawImage(img,0,0,this.getWidth(),this.getHeight(),this);
		}
}
```


----------



## André Uhres (25. Jan 2008)

Anonymous hat gesagt.:
			
		

> ..Was hat das Hintergrundbild damit zu tun?..


Es hat mit dem Layout des Bildpanels zu tun. Versuch's mal so:

```
BackGroundPane(String imagefile) {
        super(null);//<------------dies hinzufügen !
```


----------



## Guest (25. Jan 2008)

danke, hat funktioniert.

aber verstehen würd ich das auch gerne ^^

der befehl führt doch dazu, dass der konstruktor von JPanel aufgerufen wird, mit dem Objekt null.
Ohne diesen Befehl wird der Standard-Konstruktor von JPanel aufgerufen, also JPanel(), right?

Und was besagt nun dieses null?


----------



## outbreaker (25. Jan 2008)

die Übergabe von Null setzt den standard LayoutManager vom JPanel auf null


```
JPanel(LayoutManager layout)
```


----------



## André Uhres (25. Jan 2008)

Anonymous hat gesagt.:
			
		

> ..aber verstehen würd ich das auch gerne..


Der default Layout von JPanel ist FlowLayout. Da du ja NullLayout brauchst, musst du den explizit setzen :wink:
Das geht entweder über den Konstruktor, wie schon gezeigt, oder über die Methode setLayout:

```
setLayout(null);
```


----------



## Guest (25. Jan 2008)

Vielen Dank


----------



## Tom299 (25. Jan 2008)

wo wir gerade bei dem thema sind:

ich hab auch das "gleiche" problem, allerdings hab ich meine buttons usw. auf einem eigenen JPanel, das dem frame hinzugefügt wird. und dann bekomm ich einfach keine buttons usw. angezeigt. laß ich das panel weg und leg die buttons direkt auf den frame, klappts wunderbar.

gibts dafür auch eine lösung? denn die buttons auf den frame legen ist ja nicht so das gelbe vom ei, zumindest in meinem wizard keine akzeptable lösung ...


----------



## outbreaker (25. Jan 2008)

da gibt es sicher eine Lösung
nur ohne Code oder Fehlermeldung ist es schwer dir zu helfen :wink:


----------



## outbreaker (25. Jan 2008)

Kann es sein das du mit dem LayoutManager = Null arbeitest?
dann musst du beim JPanel natürlich mit setBounds die Größe und Position setzten bevor du es zum JFrame hinzufügst

mit dem setBounds gilt natürlich auch für die Buttons obwohl ich davon ausgehen das du das ja machst da es ja direkt auf dem Frage zu funktionieren scheint


----------



## Tom299 (25. Jan 2008)

ich verwende BorderLayout in dem beispiel, ist aber eigentlich egal welches ich benutze, immer der gleiche effekt. wenn man mit der maus über die buttons kommt werden sie auch dargestellt bzw. die textarea. hab beim frame auch schon validate() versucht aber bringt nix.

hier der code zum probieren:



```
package de.test;

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;

import javax.swing.JPanel;


public class ImagePanel extends JPanel {

	private Image backgroundImage = null;
	
	public ImagePanel() {
		super (new BorderLayout ());
		initComponents();
		layoutComponents();		
	}
	
	private void initComponents() {
		backgroundImage = Toolkit.getDefaultToolkit().getImage("c:/back.jpg");
	}
	
	private void layoutComponents() {
		this.setLayout(new BorderLayout ());
	}
	
    public void paint(Graphics g) {
        super.paintComponent(g);
        g.drawImage(backgroundImage,0,0,this.getWidth(),this.getHeight(),this);        
    }	
}
```


```
package de.test;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;


public class MainPanel extends JPanel {

	private JButton btnLeft = null;
	private JButton btnCenter = null;
	private JButton btnRigth = null;
	
	private JLabel lblLeft = null;
	private JLabel lblCenter = null;
	private JLabel lblRight = null;
	
	private JPanel panelLeft = null;
	private JPanel panelCenter = null;
	private JPanel panelRight = null;
	
	private JTextArea txtArea = null;
	
	private ImageIcon backgroundIcon = null;
	
	
	public MainPanel() {
		super (new BorderLayout ());
		initComponents();
		layoutComponents();
	}
	
	private void initComponents () {
		btnLeft = new JButton ("Linker Button");
		btnLeft.setOpaque(true);
		btnCenter = new JButton ("Mittlerer Button");
		btnCenter.setOpaque(true);
		btnRigth = new JButton ("Rechter Button");
		btnRigth.setOpaque(true);
		
		lblLeft = new JLabel ("Linkes Label");
		lblLeft.setOpaque(true);
		lblCenter = new JLabel ("Mittleres Label");
		lblCenter.setOpaque(false);
		lblRight = new JLabel ("Rechtes Label");
		lblRight.setOpaque(true);
		
		panelLeft = new JPanel (new FlowLayout ());
		panelLeft.setOpaque(true);
		panelCenter = new JPanel (new BorderLayout ());
		panelCenter.setOpaque(false);
		panelRight = new JPanel (new FlowLayout ());
		panelRight.setOpaque(true);
		
		txtArea = new JTextArea ();
		txtArea.setPreferredSize(new Dimension (120,80));
		txtArea.setLineWrap(true);
		txtArea.setOpaque(true);
		
		backgroundIcon = new ImageIcon ("C:/icon.png");
		btnRigth.setIcon(backgroundIcon);		
	}
	
	private void layoutComponents () {
		this.setLayout(new BorderLayout ());
		
		panelLeft.add(lblLeft);
		panelLeft.add(btnLeft);
		
		panelRight.add(lblRight);
		panelRight.add(btnRigth);		
		
		panelCenter.add(lblCenter, BorderLayout.NORTH);
		panelCenter.add(txtArea, BorderLayout.CENTER);
		panelCenter.add(btnCenter, BorderLayout.SOUTH);
		
		this.add(panelLeft, BorderLayout.WEST);
		this.add(panelCenter, BorderLayout.CENTER);
		this.add(panelRight, BorderLayout.EAST);
	}	
}
```


```
package de.test;

import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.JFrame;


public class StartApp {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		JFrame frame = new JFrame ("Test Backgroud Image");
		frame.getContentPane ().setLayout(new BorderLayout ());
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLocationRelativeTo(null);
		frame.setSize(new Dimension (640,480));		

		MainPanel  mainPanel = new MainPanel ();		
		frame.setContentPane(new ImagePanel ());
		frame.getContentPane().add(mainPanel, BorderLayout.CENTER);
		frame.setVisible(true);		
	}
}
```


----------



## outbreaker (25. Jan 2008)

mit dem 
	
	
	
	





```
frame.setContentPane(new ImagePanel ());
```
 überschreibst du den Container für dein Objekte auf dem JFrame da kannst du soweit ich weiß nicht einfach ein JPanel für einsetzen

API



> setContentPane
> 
> public void setContentPane(Container contentPane)
> 
> ...



Du solltest für deinen eigenen Container das Interface RootPaneContainer verwenden und nicht JPanel


----------



## Tom299 (25. Jan 2008)

aber oben in dem anderen code-beispiel ist es doch genauso drin und das klappt ja auch, solange die buttons auf dem frame selbst liegen. oder ist obiges beispiel eigentlich auch falsch? ;-)


```
/* set background picture for window */
        main.setContentPane(new BackGroundPane("menu.jpg"));
```


----------



## outbreaker (25. Jan 2008)

na das oben scheint ja zu gehen also kann es ja nur ein kleiner Fehler bei deinem sein
ich gucke es mir gerade nochmal an


----------



## Tom299 (25. Jan 2008)

ich hab es jetzt mal mit


```
public class ImagePanel extends JRootPane
```

versucht, aber gleiches verhalten.

dann hab ich auch mal:

```
MainPanel  mainPanel = new MainPanel ();
		ImagePanel imagePanel = new ImagePanel ();		
		imagePanel.add (mainPanel);		
		frame.setContentPane(imagePanel);
```

versucht, aber auch das gleiche.

wenn ich es umgekehrt mache, also das imagePanel ins mainPanel, dann siehts noch schlechter aus ;-)


----------



## outbreaker (25. Jan 2008)

so jetzt hab ichs gesehen wo der Unterschied ist 

du Überschreibst die paint Methode und nicht die paintComponent :wink:


----------



## Tom299 (25. Jan 2008)

```
//    public void paint(Graphics g) {
//        super.paint(g);
//        g.drawImage(backgroundImage,0,0,this.getWidth(),this.getHeight(),this);        
//    }	
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(backgroundImage,0,0,this.getWidth(),this.getHeight(),this);
     }
```

jetzt wird gar kein bild im hintergrund mehr gezeichnet ... langsam glaub ich java will bei mir keine hintergrundbilder haben  :shock:


----------



## outbreaker (25. Jan 2008)

das Problem liegt darin das die paintComponent Methode gar nicht aufgerufen wird
nur warum verstehe ich noch nicht


----------



## Tom299 (25. Jan 2008)

mir ist noch aufgefallen daß die paint-methode auch nur funktioniert wenn ich darin anstatt super.paint die super.paintComponent aufrufe :shock: 


```
public void paint(Graphics g) {
//        super.paint(g);
        super.paintComponent(g);
        g.drawImage(backgroundImage,0,0,this.getWidth(),this.getHeight(),this);       
    }
```


----------



## outbreaker (25. Jan 2008)

Das muss irgendwie mit dem LayoutManager zusammenhängen das bei dir das Bild nicht angezeigt wird
bei LAyoutManager Null funktioniert es ja  :autsch:


----------



## hdi (25. Jan 2008)

ersetz mal im Konstruktor deines eigenen Panels:


```
super (new BorderLayout ());
```

durch:


```
super (new BorderLayout (null));
```

du verwendest damit ja den Konstruktor von JPanel, und so wie ich das verstanden habe, muss man den explizit auf null setzen sonst ist es FlowLayout.

mfg


----------



## outbreaker (25. Jan 2008)

leider geht das nicht es gibt beim BorderLayout keinen Konstruktor den man NULL setzen kann
Du solltest bei dir super(null) machen da du bei dir dann den LAyoutManager auf Null setzt aber das BorderLAyout kannst du nicht mit Null Instanzieren

Wenn es bei dir Funktioniert mit dem Hintergund Bild könntest du da mal den Gesamten Funktionierenden Quellcode posten

Es sein den er ist 100 Seiten lang  :wink: 

oder nen einfaches funktionierendes Beispiel?


----------



## Guest (26. Jan 2008)

achso, okay. bin eben noch anfänger 

hier ist mal mein code, aber ich benutze ja wie gesagt nicht das BorderLayout. 
Weiss nicht inwiefern meine Klassen auch bei anderen Layouts funktionieren:


```
public class BackGroundPane extends JPanel{
      Image img = null;

      BackGroundPane(String imagefile) {
      	 super(null);          // hier musst du jetzt wissen, wie du das bei dir machen willst.
         if (imagefile != null) {
            MediaTracker mt = new MediaTracker(this);
            img = Toolkit.getDefaultToolkit().getImage(imagefile);
            mt.addImage(img, 0);
            try {
               mt.waitForAll();
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
         }
      }

      protected void paintComponent(Graphics g) {
         super.paintComponent(g);
         g.drawImage(img,0,0,this.getWidth(),this.getHeight(),this);
      }
}
```


```
public class BaseFrame extends JFrame{
	
	public BaseFrame(String title){
		
		/* create and set window */
		super(title);
		setLayout(null);    // musst du wohl auch ändern
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(500,500);
		setLocation(
        	(Toolkit.getDefaultToolkit().getScreenSize().width-
         	getSize().width) / 2,
        	(Toolkit.getDefaultToolkit().getScreenSize().height-
         	getSize().height) / 2);
         
        /* load background picture */
        setContentPane(new BackGroundPane("icon/menu.jpg"));
        
        /* load button */
        final AbstractButton startGame = new JButton(new ImageIcon("icon/startGame.jpg"));
        startGame.setBounds(40,90,150,150);
        add(startGame);
}
```


```
import javax.swing.JFrame;
public class Game{
	
	public static void main(String[] args){
		
		BaseFrame window = new BaseFrame("my window");
		window.setVisible(true);
	}
}
```


----------



## Tom299 (28. Jan 2008)

jemand ne lösung gefunden oder funktioniert das jetzt nur mit dem null-layout? dann ist es wohl ein bug oder ein feature von sun? ;-)


----------



## outbreaker (28. Jan 2008)

ich habe leider noch keine Lösung gefunden  :cry: 
Sobald ich eine habe werde ich Sie posten


----------

