# Panels stapeln, geht das?



## bloodyrocky (26. Mai 2010)

Hi,

der Titel lässt vermuten, dass es sich um etwas einfaches Handeln sollte, aber im Endeffekt scheint es doch schwieriger.

Ich versuche gerade ein App zu schreiben bei der ich mehrere Panels transparent übereinander legen möchte. D.h. ich habe ein Panel welches sich in der Mitte des Frames befindet, oben (NORTH) und unten (SOUTH) befindet sich jeweils ein anderes Panel.

```
JPanel centerPanel = new JPanel;
centerPanel.setBackground(Color.orange); //Aus Debuggründen
```
Darin lege ich ein Panel mit Buttons, eins mit einer Grafik und eines mit einer Grafik die auf und ab läuft ab.

```
centerPanel.add(buttonPanel, BorderLayout.SOUTH);
centerPanel.add(grafikPanel, BorderLayout.CENTER);
centerPanel.add(animierteGrafikPanel, BorderLayout.CENTER);
```

Soweit so gut, das Panel mit der animierten Grafik wurde transparent gesetzt, so dass normalerweise das Grafikpanel durchscheint werden sollte. Tatsächlich ist das aber nicht der Fall, sondern das centerPanel scheint hindurch.

Danach habe ich versucht das centerPanel statt als JPanel als JLayeredPane zu definieren, aber das legt sich dann über die komplette Form und nicht nur in die Mitte der Form, also umschlossen von den Panels oben und unten. Hinzu kam, dass sich die darauf befindlichen JPanels auch nicht anordnen ließen.

Ziel ist es in dem centerPanel eine 2 Animationen (sich auf und ab bewegende Bilder) und ein Bild die übereinander liegen abzubilden, die Reihenfolge wäre Bild ganz unten, dann 1. Animation und als oberstes die 2. Animation.

Ich hoffe jemand kann mich in die richtige Richtung stupsen.
Vielen Dank!


----------



## U2nt (26. Mai 2010)

Entweder indem du manuell die Bounds sets wenne das Layout auf null setzt, oder mit einem CardLayout.
Mit einem CardLayout kannse Panels nach vorne holen und auch wieder nach hinten schieben, bzw ein anderes nach vorne holen.


----------



## bloodyrocky (26. Mai 2010)

Die Bounds habe ich versucht manuell zu setzen, werden aber ignorier. Ich habe in meiner Klasse für die Panels (sowohl für die Animationen, als auch die Bilder) die PreferedSize auf die größe des Bildes gesetzt. Das CardLayout funktioniert nicht, da immer nur ein Panel sichtbar ist und die anderen dahinter liegen ich brauche aber alle 3 Panels sichtbar, evtl. auch noch ein 4.

Hat noch jemand eine Idee? Habe ich mich eigentlich verständlich ausgedrückt, oder denke ich vielleicht wieder viel zu kompliziert?

Im Prinzip ist die Frage ja kann ich mehrere Panels übereinander legen und alle für den Benutzer sichtbar machen und wenn ja wie? Mit meiner Vorgehensweise funktioniert es wohl nicht


----------



## Verjigorm (27. Mai 2010)

bloodyrocky hat gesagt.:


> Die Bounds habe ich versucht manuell zu setzen, werden aber ignorier.



Null-Layout auch gesetzt?


----------



## Michael... (27. Mai 2010)

Würde eine Komponente mit selbstgeschriebenem LayoutManager verwenden:

```
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.LayoutManager;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class PanelPileDemo extends JFrame {
	public PanelPileDemo() {
		this.getContentPane().add(new JLabel("NORTH", JLabel.CENTER),
				BorderLayout.NORTH);
		this.getContentPane().add(new JLabel("SOUTH", JLabel.CENTER),
				BorderLayout.SOUTH);
		PilingPanel pile = new PilingPanel();
		this.getContentPane().add(pile, BorderLayout.CENTER);
		pile.add(new JComponent() {
			private int x=20, y=20;
			{
				new Thread(new Runnable() {
					public void run() {
						while (true) {
							int w = getWidth(), h = getHeight();
							x += 20;
							y += 10;
							if (x > w) x = 20;
							if (y > h) y = 20;
							repaint();
							try {
								Thread.sleep(200);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
				}).start();
			}
			
			public void paintComponent(Graphics g) {
				super.paintComponent(g);
				g.setColor(Color.RED);
				g.fillOval(x, y, 15, 15);
			}
		});
		pile.add(new JComponent() {
			private int x=20, y=20;
			{
				new Thread(new Runnable() {
					public void run() {
						while (true) {
							int w = getWidth(), h = getHeight();
							x += 10;
							y += 10;
							if (x > w) x = 20;
							if (y > h) y = 20;
							repaint();
							try {
								Thread.sleep(100);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
				}).start();
			}
			
			public void paintComponent(Graphics g) {
				super.paintComponent(g);
				g.setColor(Color.BLUE);
				g.fillOval(x, y, 15, 15);
			}
		});
		pile.add(new JComponent() {
			private int x=20, y=20;
			{
				new Thread(new Runnable() {
					public void run() {
						while (true) {
							int w = getWidth(), h = getHeight();
							x += 10;
							y -= 10;
							if (x > w) x = 20;
							if (y <= 0) y = h;
							repaint();
							try {
								Thread.sleep(100);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
				}).start();
			}
			
			public void paintComponent(Graphics g) {
				super.paintComponent(g);
				g.setColor(Color.GREEN);
				g.fillOval(x, y, 15, 15);
			}
		});
		JPanel panel = new JPanel();
		panel.setBackground(Color.CYAN);
		pile.add(panel);
	}

	class PilingPanel extends JPanel implements LayoutManager {
		private Dimension dimension = new Dimension(100, 100);
		private List<Component> components;

		public PilingPanel() {
			this.setLayout(this);
			components = new ArrayList<Component>();
		}

		public Component add(Component comp) {
			this.components.add(comp);
			return super.add(comp);
		}

		public void layoutContainer(Container parent) {
			int w = parent.getWidth(), h = parent.getHeight();
			for (int i = 0; i < components.size(); i++)
				components.get(i).setBounds(0, 0, w, h);
		}

		public void addLayoutComponent(String name, Component comp) {
		}

		public Dimension minimumLayoutSize(Container parent) {
			return dimension;
		}

		public Dimension preferredLayoutSize(Container parent) {
			return dimension;
		}

		public void removeLayoutComponent(Component comp) {
		}
	}

	public static void main(String[] args) {
		JFrame frame = new PanelPileDemo();
		frame.setBounds(0, 0, 500, 300);
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
}
```


----------



## bloodyrocky (27. Mai 2010)

Danke Michael, wie du es in deiner Demo zeigst funktioniert es und tut in etwa das was ich will. Werde es mir genauer anschauen.

Vielen Dank!


----------



## DocTylerDurden (30. Mai 2010)

das problem bei deiner ausgangsvariante ist glaub ich, dass du nicht 2 panels an die gleiche stelle des layouts setzen kannst, dann wird die 1te gelöscht.
aber um das zu lösen musst dus glaubich nich so umständlich machen mit neuen layouts oder sonstwas. ich hab eimfach die panels ineinadner geaddet, anstatt auf das tiefstliegende. das sieht dann so aus:

```
main.add(colourGrid);
    FlowLayout flow0 = new FlowLayout();
    flow0.setHgap(0);
    flow0.setVgap(0);
    colourGrid.setLayout(flow0);
    //colourGrid.setOpaque(false);

    colourGrid.add(masterExploder);
    masterExploder.setBackground(grey);
    masterExploder.setPreferredSize(new Dimension(width*20, height*20));
    masterExploder.setOpaque(false);
    masterExploder.setLayout(flow0);
    
    masterExploder.add(backSurface);
    backSurface.setOpaque(false);
```

masterExploder ist ein panel was vorher schon definiert wurde, seine einbindung ist repräsentativ für das prinzip. ich hoffe das hilft dir.


----------



## bloodyrocky (31. Mai 2010)

Ja genau, das Problem ist, dass man 2 Panels nicht an der gleichen Position platzieren kann. Sobald ich das 2 an die gleiche Position platziert habe wurde das erste "gelöscht". Ich habe im Nachhinein festgestellt, das es unnötig war Panels zu verwenden und habe es mit Labels gelöst, da es sich um Bilder handelt, die animiert werden sollen. Aber auch hier taten sich neue Probleme auf, die ich zwar beheben konnte, leider aber nicht den Grund genau nachvollziehen kann.

Werde mir aber deine Lösung auch mal genauer anschauen, aber wenn ich richtig sehe, war mein Fehler einfach nur, dass ich beide Panels an der gleichen Position in das main Panel gelegt habe. Richtig gewesen wäre es wohl, wenn ich mainPanel.add(unteresPanel) und unteresPanel.add(oberesPanel) gemacht hätte und bei beiden die Opaque auf false gestellt hätte. Dann sollte es funktionieren. Nur ist es dann auch wieder etwas komplizierter mit der Animation.

Grüße BR


----------

