JFrame mit background bild -> verschiebt Buttons ?

  • Themenstarter Themenstarter Guest
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
G

Guest

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

Code:
        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)

Code:
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);
		}
}
 
Anonymous hat gesagt.:
..Was hat das Hintergrundbild damit zu tun?..
Es hat mit dem Layout des Bildpanels zu tun. Versuch's mal so:
Code:
   BackGroundPane(String imagefile) {
        super(null);//<------------dies hinzufügen !
 
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?
 
die Übergabe von Null setzt den standard LayoutManager vom JPanel auf null

Code:
JPanel(LayoutManager layout)
 
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:
Code:
setLayout(null);
 
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 ...
 
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
 
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:


Code:
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);        
    }	
}

Code:
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);
	}	
}

Code:
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);		
	}
}
 
mit dem
Code:
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)

Sets the contentPane property. This method is called by the constructor.

Swing's painting architecture requires an opaque JComponent in the containment hiearchy. This is typically provided by the content pane. If you replace the content pane it is recommended you replace it with an opaque JComponent.

Specified by:
setContentPane in interface RootPaneContainer

Parameters:
contentPane - the contentPane object for this frame
Throws:
IllegalComponentStateException - (a runtime exception) if the content pane parameter is null
See Also:
getContentPane(), RootPaneContainer.setContentPane(java.awt.Container), JRootPane

Du solltest für deinen eigenen Container das Interface RootPaneContainer verwenden und nicht JPanel
 
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? ;-)

Code:
        /* set background picture for window */
        main.setContentPane(new BackGroundPane("menu.jpg"));
 
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
 
ich hab es jetzt mal mit

Code:
public class ImagePanel extends JRootPane

versucht, aber gleiches verhalten.

dann hab ich auch mal:
Code:
		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 ;-)
 
so jetzt hab ichs gesehen wo der Unterschied ist

du Überschreibst die paint Methode und nicht die paintComponent :wink:
 
Code:
//    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:
 
mir ist noch aufgefallen daß die paint-methode auch nur funktioniert wenn ich darin anstatt super.paint die super.paintComponent aufrufe :shock:

Code:
    public void paint(Graphics g) {
//        super.paint(g);
        super.paintComponent(g);
        g.drawImage(backgroundImage,0,0,this.getWidth(),this.getHeight(),this);       
    }
 
Das muss irgendwie mit dem LayoutManager zusammenhängen das bei dir das Bild nicht angezeigt wird
bei LAyoutManager Null funktioniert es ja :autsch:
 
ersetz mal im Konstruktor deines eigenen Panels:

Code:
 super (new BorderLayout ());

durch:

Code:
 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
 
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?
 
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:

Code:
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);
      }
}

Code:
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);
}

Code:
import javax.swing.JFrame;
public class Game{
	
	public static void main(String[] args){
		
		BaseFrame window = new BaseFrame("my window");
		window.setVisible(true);
	}
}
 
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? ;-)
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben