# Button auf Bild/ JLayeredPane in Jpanel



## Haribald (22. Okt 2008)

Hallo, 


ich habe mal wieder eine Frage, bei der ich nicht weiterkomme.
Ich verwende in einer recht verschachtelten Gui ein JPanel, in welchem ein Bild angezeigt wird.
Ich möchte nun im unteren Rand dieses Panels 2 Buttons anzeigen lassen und zwar direkt auf dem Bild.

Lösen wollte ich das ursprünglich mit der JLayeredPane, das Problem ist nur, die funktioniert  nicht in einem JPanel, sondern nur in einem JFrame.
Bei einer GlassPane siehts ja ähnlich aus.

Hat jemand eine Idee, wie ich das sonst lösen könnte?


Gruß

Haribald


----------



## Landei (22. Okt 2008)

Wie zeigst du das Bild an?

Eine Lösungsidee wäre, das Bild mit der paint() Methode des Panels zu malen, also sozusagen als "Hintergrund". 

Das Panel würde ich
- entweder auf BorderLayout setzen und im Süden dann ein *durchsichtiges* Unterpanel (FlowLayout oder GridLayout) mit den beiden Knöppen adden
- oder mit dem GridBagLayout kämpfen, bis die Knöppe da sind wo sie sein sollen


----------



## Haribald (22. Okt 2008)

Hallo Landei,

vielen Dank für die Antwort,
darf ich fragen, wie ich ein durchsichtiges UnterPanel erstelle? Einfach ein Panel mit setOpaque(true)?

Hier mal eine abgewandelte LayeredPane Demo, die die Geschichte verdeutlicht


```
import java.awt.BorderLayout;
import java.awt.Container;

import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.*;

public class JLayeredPaneSample {
  public static void main(String args[]) {
	JLayeredPane desktop = new JDesktopPane();
    JFrame f = new JFrame("JDesktopPane Sample");
    JPanel left=new JPanel();
    	left.setBorder(BorderFactory.createTitledBorder("Where is the Layered Pane?"));
    JPanel right=new JPanel();
    	right.setBorder(BorderFactory.createTitledBorder("Right Panel"));
    JSplitPane sP=new JSplitPane();
    	sP.setDividerLocation(150);
    left.setOpaque(true);
    
    
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container content = f.getContentPane();
    
    desktop.setOpaque(false);
    desktop.add(createLayer("Open 1"), JLayeredPane.POPUP_LAYER);
    desktop.add(createLayer("Iconified"), JLayeredPane.DEFAULT_LAYER);
    desktop.add(createLayer("Open 2"), JLayeredPane.PALETTE_LAYER);
    
    left.add(desktop);
    sP.add(left,JSplitPane.LEFT);
    sP.add(right,JSplitPane.RIGHT);
    
    content.add(sP, BorderLayout.CENTER);
    f.setSize(300, 200);
    f.setVisible(true);
  }

  public static JInternalFrame createLayer(String label) {
    return new SelfInternalFrame(label);
  }

  static class SelfInternalFrame extends JInternalFrame {
    public SelfInternalFrame(String s) {
      getContentPane().add(new JLabel(s), BorderLayout.CENTER);
      setBounds(50, 50, 100, 100);
      setResizable(true);
      setClosable(true);
      setMaximizable(true);
      setIconifiable(true);
      setTitle(s);
      setVisible(true);
    }
  }
}
```


----------



## Haribald (22. Okt 2008)

Opaque(false) meinte ich natürlich


----------



## Haribald (22. Okt 2008)

Ein Wort zur Anzeige der Bilder:

Das bild wird über die Instanz einer Klasse angezeigt, die von JComponent abgeleitet wird und kann dadurch direkt in das Panel gelegt werden. 
Daran kann ich nichts ändern, sonst verhauts mir das gesamte restliche Programm.

Ich hab jetzt mal versucht 2 Panels übereinander in den linken Teil der SplitPane (beider BorderLAyout.North) zu legen. Die untere beinhaltet das Bild, die obere nur einen Button.
Leider wird unabhängig von setOpaque das Bild (-die untere Pane) nicht mehr angezeigt.

Hat jemand eine Idee?

Gruß

Haribald


----------



## André Uhres (22. Okt 2008)

Versuch's mal so:

```
...
        JPanel left = new JPanel(new BorderLayout());
...
        public SelfInternalFrame(String s) {
            setOpaque(false);
            setBackground(new Color(0f, 0f, 0f, 0f));
...
```
So müssten die JInternalFrames durchsichtig sein. Allerdings bin ich nicht sicher, was du überhaupt willst  :?


----------



## Haribald (22. Okt 2008)

Hallo, danke, für deine Antwort.

Bin mir jetzt leider nicht sicher, ob sich deine Antwort auf die Version mit der LayeredPane oder dem durchsichtigen Panel bezieht.?

Ich setz mal mein Beispiel mit dem Panel drunter, die Klasse ImageComponent ist auch dabei,-also lauffähig.
Wie ma sieht überrschreibt das obere Panel das untere, ich hätte den Button aber gerne direkt auf dem Bild.



```
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.*;
import javax.swing.*;

public class JLayeredPaneSample {
  public static void main(String args[]) {
	
    JFrame f = new JFrame("JDesktopPane Sample");  
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container content = f.getContentPane();
    
    //Grundaufbau
    JPanel left=new JPanel();
    	left.setBorder(BorderFactory.createTitledBorder("Where is the Picture Panel?"));
    	left.setLayout(new BorderLayout());
    JPanel right=new JPanel();
    	right.setBorder(BorderFactory.createTitledBorder("Right Panel"));
    JSplitPane sP=new JSplitPane();
    	sP.setDividerLocation(150);
    	
    //Oberes Panel
    final JPanel glass=new JPanel();
    glass.setOpaque(false);
    glass.setBackground(new Color(0f, 0f, 0f, 0f)); 
    JButton test=new JButton("klick");
    glass.setLayout(new FlowLayout());
    glass.add(test);   
    
    test.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
			glass.setVisible(false);
		}
	});  
    
   //Unteres Panel
    JPanel back=new JPanel();    
    BufferedImage buf=new BufferedImage(500,500,BufferedImage.TYPE_BYTE_GRAY);
    Graphics2D g = buf.createGraphics();
	g.setColor(Color.BLACK);
	g.fillRect(0, 0, 500, 500);
	g.setColor(Color.WHITE);
	g.fillRect(100, 100, 200, 200);
	ImageComponent iC=new ImageComponent(buf);
	back.add(iC);
    
    left.add(back,BorderLayout.NORTH);
    left.add(glass,BorderLayout.NORTH); //Hier auskommentieren um das Bild zu sehen
    sP.add(left,JSplitPane.LEFT);
    sP.add(right,JSplitPane.RIGHT);
    
    content.add(sP, BorderLayout.CENTER);
    f.setSize(300, 200);
    f.setVisible(true);
  } 
}

class ImageComponent extends JComponent{
	
	private BufferedImage 	image;
				
	public BufferedImage getImage(){return image;}
	
	
	
	public ImageComponent(BufferedImage image){
		this.image=image;
		setPreferredSize (new Dimension (image.getWidth(null),image.getHeight(null)));
	}
	
	public void paintComponent (Graphics g){
		g.drawImage(image,0,0,null);
	}
	
}
```


----------



## André Uhres (23. Okt 2008)

Ich seh da aber kein JLayeredPane.
Die fünf Bereiche von BorderLayout können jeweils nur eine einzige Komponente aufnehmen.
In einem JLayeredPane ist standardmäßig kein Layoutmanager eingestellt. 
Daher müssen alle integrierten Komponenten feste Positionsangaben und Größen haben. 
Dazu kann man beispielsweise die Methode setBounds(int x, int y, int width, int height) benutzen.
Wenn man einem JLayeredPane einen Layoutmanager zuordnet, 
so werden alle Komponenten gemäß den Richtlinien so angeordnet, als wären sie alle in einer Ebene.
Siehe auch: How to Use Layered Panes. Dort findest du auch den Abschnitt "Laying Out Components in a Layered Pane".

Mein erster Beitrag bezieht sich übrigens auf diese Version: http://www.java-forum.org/de/viewtopic.php?p=458176#458176


----------



## Haribald (23. Okt 2008)

Hallo,

danke für deine Antwort.
Was ich mit dem zweiten Beispiel (ohne LayeredPane) zeigen wollte, ist der stark vereinfachte Aufbau meines Programms.

- eine SplitPane, darin in der Links- und Rechtskomponente Panels.


Ich möchte nun in einem dieser Panels (im Beispiel das Linke) mehrere Komponenten übeinander legen und zwar einmal eine ImageComponente (siehe Beispiel -ein Bild) und darüber mehrere Buttons.
Im Endergebnis sollen die Buttons also direkt auf dem Bild sein.

Ich muss das nicht zwangsweise mit einer LayeredPane lösen, wichtig ist mir nur es irgendwie zu lösen ;-)
Die Anforderungen und Beschränkungen der LayeredPane kenne ich. Das Problem das ich habe ist dieses, dass ich meines Wissens keine LayeredPane in ein JPanel stecken kann, sondern nur in Frames.

Die Frage ist , wie erreich ich es, im linken Teil der SplitPane mehrere Komponenten übereinander zu legen, so dass die unteren (in dem Fall das Bild) noch zu sehen sind?

Hoffe es ist etwas klarer geworden

Gruß

Haribald


----------



## André Uhres (23. Okt 2008)

Versuch mal den JButton einfach der Bildkomponente hinzuzufügen. Beispiel:

```
//left.add(glass,BorderLayout.NORTH); //Hier auskommentieren um das Bild zu sehen
iC.setLayout(new FlowLayout());
JButton bt = new JButton("klick");
iC.add(bt);
```
(das ist im im Prinzip die Lösung, die schon in der allerersten Antwort vom Landei vorgeschlagen wurde)


----------



## Haribald (24. Okt 2008)

Hallo André


Vielen Dank für die Antwort.
Auf die Idee, das direkt in die ImageComponente zu legen bin ich absolut nicht gekommen. 
Vielen vielen Dank dafür, jetzt bin ich fast am Ziel.
Die erste Antwort hatte ich so verstanden, wie ich sie im zweiten Beispiel umgesetzt habe, nämlich eine neues
Panel zu erstellen, dass ich auf Durchsichtig stelle. (Panel glass)
Da hab ich wohl etwas falsch verstanden.

Ich hätte eine ergänzende Frage:
Die Bilder der ImageComponent können sehr unterschiedlicher Größe sein. Aus diesem Grund liegt die ImageComponent selbst noch in einem ScrollPanel.
Wenn ich den Button nun an den unteren Teil des Bildes hänge wir er somit mitunter erst durch Scrollen sichtbar.
In diesem Fall wäre es also sinnvoller, den Butto z.B. an die ScrollPane zu hängen, um ihn immer Beispielsweise im rechten untere Eck zu haben. Das Bild wird beim Scrollen also unter dem Button wegbewegt.
Lässt sich das auch realisieren?

Gruß

Haribald


----------



## André Uhres (24. Okt 2008)

Wir können ein JPanel mit OverlayLayout erstellen. Dort kommt dann *zuerst* der JButton hinein
und dann die BildKomponente:

```
...
        JPanel jPanel1 = new JPanel() {
            @Override
            public boolean isOptimizedDrawingEnabled() {
                return false;
            }
        };
        jPanel1.setLayout(new OverlayLayout(jPanel1));
        JPanel jPanel2 = new JPanel(new BorderLayout());
        jPanel2.setOpaque(false);
        JPanel jPanel3 = new JPanel();
        jPanel3.setPreferredSize(new Dimension(0, 50));
        jPanel3.setOpaque(false);
        jPanel3.add(new JButton("klick"));
        jPanel2.add(jPanel3, BorderLayout.SOUTH);

        jPanel1.add(jPanel2);//zuerst der JButton
...
        jPanel1.add(new JScrollPane(iC));//dann die Bildkomponente

        sP.add(jPanel1, JSplitPane.LEFT);
...
```


----------



## Haribald (24. Okt 2008)

Super,

funktioniet einwandfrei.
Ganz herzlichen Dank für dein Geduld und Hilfe André.
Den anderen natürlich auch 

Gruß

Haribald


----------



## André Uhres (24. Okt 2008)

Haribald hat gesagt.:
			
		

> Super,funktioniet einwandfrei.


Wenn du registriert wärst, könntest du das jetzt abhaken :wink:


----------



## Haribald (28. Okt 2008)

Da ist was dran, sorry,

Werde das nachholen

Gruß

Haribald


----------



## redchili (29. Okt 2008)

Haribald hat gesagt.:
			
		

> ... Lösen wollte ich das ursprünglich mit der JLayeredPane, das Problem ist nur, die funktioniert  nicht in einem JPanel, sondern nur in einem JFrame. ...


Hallo!

Was genau funktioniert denn nicht mit JLayeredPane (jlp) in einem JPanel (jp)?
Ich habe ein grob ähnliches Problem wie Du und habe nach einiger herumprobiererei nun herausbekommen, dass es doch geht.
Warum es bei mir zunächst so schien, als ob es nicht ginge (Inhalte der JLayeredPane waren nicht sichtbar) war, dass ich vergessen hatte, bei der JLayeredPane eine Grösse, zu setzen (null-Layoutmanager) und diese somit 0x0 gross war.

Was mich skeptisch gemacht hatte war: 
	
	
	
	





```
// frame-creation etc
JPanel jp = new JPanel();

// add jp to frame here ... 
 
JLayeredPane jlp = new JLayeredPane();

jp.add(jlp);

// add some components to jlp here...

jp.getComponentCount();   // returns 1! so there must be something...
dpl.getComponentCount();  // also returns the correct number of added components
```
also nicht vergessen (am besten gleich bei der erzeugung vom jlp-Objekt: 
	
	
	
	





```
jlp.setSize(xSize, ySize);
```
Grüsse, red


----------

