# Ärger mit JLayeredPane :-(



## Bernie (25. Jun 2007)

Hallo, 
ich hänge derzeit fest mit JlayeredPane, und das bringt mich langsam zum verweiflen :'-( 

in einem JLayeredPane (null Layout) habe ich 4 verschiedene Panels, die frei platzierbar sind

die Panels werden in einer Schleife dem LayeredPane hinzugefügt, und zwar so:


```
int i = 1;

  for (Iterator iter = panels.iterator(); iter.hasNext();) {
      
      CustomPanel cP = (CustomPanel) iter.next();

      layeredPane.add(cP, new Integer(i++));
      cP.setBounds(...);     
    }
```


Nun habe ich 4 Panels die mit index (1,2,3,4) in den layeredpane (richtig) eingefügt worden sind.

Diese Panels haben nun ein JPopupMenu, für jedes dieser Panels soll es nun die Möglichkeit geben, 
das aktuell selektierte "eine Ebene nach vorne", oder "eine ebene nach hinten" zu bringen.
im entsprechenden ActionListener versuche ich dies:


```
public void actionPerformed(ActionEvent e) {
     
      String source = ((JMenuItem)e.getSource()).getActionCommand();

      if(source.equals("eine ebene nach vorne")) {  

         //cP.getLayerPosition() gibt den Layer-index des selektierten Panels zurück (1,2,3,4)
        //setLayer(cP, 1, cP.getLayerPosition()) zB. führt nur zu teilweise richtigem, und für
        // mich nicht nachvollziebarem Verhalten
       // außerdem scheint moveToFront immer ein rücken in die oberste Ebene zu machen
	//was muss ich hier tun, damit das selektierte Panel "eine ebene" nach oben rückt ?
        setLayer(cP, cP.getLayerPosition(),cP.getLayerPosition());
        moveToFront(cP);      
      }          
      
}
```

Ich habe auch anderes in der setLayer Methode probiert, nichts führt zum Erfolg. Bitte, was mache ich hier falsch ?


Vielen Dank schonmal.

Beste Grüße

Bernie

_[Edit by Beni: Codetags repariert, / und nicht \ verwenden!]_


----------



## Marco13 (25. Jun 2007)

Du kennst
http://java.sun.com/docs/books/tutorial/uiswing/components/layeredpane.html
??? 
Poste ggf. mal ein Kleines, Compilierbares Beispiel (kannst ja die CustomPanels durch eigene ersetzen usw.)


----------



## Bernie (25. Jun 2007)

hallo nochmal, 
hier nun mal ein ausführbares Beispiel, das mein Problem zeigen soll:

Wenn ich nun z.B. das PopupMenu über dem Label mit layer index 2 aufrufe, und den eintrag "eine ebene nach vorne" auswähle, tauschen das weiße und das schwarze Jlabel quasi den platz und das weiße rückt eben über das schwarze, bleibt aber hinter dem grauen...usw

ich kapier das nicht mit den layern. ja, das sun beispiel kenne ich , und kann mir trotz stundenlangem anguckens bis dato nichts übertragen :'-((


```
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;


public class LayeredPaneTest extends JLayeredPane {

	DragableLabel layerLabel;
	Color [] background = {Color.GREEN, Color.BLUE, Color.WHITE, Color.BLACK, Color.GRAY};
	JPopupMenu popup;
	JMenuItem moveOneBehind, moveOneBefore;

	public LayeredPaneTest() {		
		
		
		initPopupMenu();

		for(int i = 0;i<5;i++) {
		  layerLabel = new DragableLabel();		
		  layerLabel.setText("Label mit Layer Index " + i);
		  layerLabel.setBorder(new LineBorder(Color.BLACK));
          layerLabel.setBackground(background[i]);
		  layerLabel.setBounds(i+(i*100),i+(i*100),180,180);
		  
		  
		  this.add(layerLabel, new Integer(i));	  
			
		}	
		
		//ActionListener für PopupMenu,Layer index soll verändert werden
		moveOneBefore.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e){
				
				//??? 
				 setLayer(layerLabel,0,1);			    
//			     moveToFront(layerLabel);			      
			}			
		});		
	}
	
	public void initPopupMenu(){
		
		moveOneBehind = new JMenuItem("Eine Ebene nach hinten");	     
	    moveOneBefore = new JMenuItem("eine ebene nach vorne");
	    popup = new JPopupMenu();    
	    popup.add(moveOneBefore);    
	    popup.add(moveOneBehind);		
	}

	public static void main(String args []){
		
		JFrame f = new JFrame();
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setContentPane(new LayeredPaneTest());
		f.setSize(new Dimension(700,700));
	    f.setLocationRelativeTo(null);
	    f.setTitle("Layer Test :-(");
		f.setVisible(true);
	}
	
	/**
	 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	 * Code stammt teilweise von 
	 * [url]http://www.dpunkt.de/java/Programmieren_mit_Java/Oberflaechenprogrammierung/18.html[/url]
	 *
	 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	 */
	class DragableLabel extends JLabel implements MouseListener, MouseMotionListener {		
	
		 int startPoint = 0;
		 int originalLayer;
		 Point offsetPoint = null;

		 DragableLabel() {
			 
		   setHorizontalAlignment(SwingConstants.CENTER);	
		   setOpaque(true);	
		   startPoint += 20;	
		   setBounds(startPoint, startPoint, 50, 50);
		   addMouseListener(this);
		   addMouseMotionListener(this);
		 }
		 
		 public void mouseReleased(MouseEvent e){

			 if(e.getButton() == MouseEvent.BUTTON3) {
			     popup.show(DragableLabel.this,e.getX(),e.getY());
			 }

		 }
		     
		 public void mousePressed(MouseEvent e) {	
			offsetPoint = new Point (e.getPoint ().x,e.getPoint ().y);			
		   
		 }
			   
		 public void mouseDragged(MouseEvent e){
		   if (offsetPoint != null)
			 setLocation (getX () + (e.getX () - offsetPoint.x),getY () + (e.getY () - offsetPoint.y));
			
		 }

			public void mouseClicked(MouseEvent arg0) {}

			public void mouseEntered(MouseEvent arg0) {}
			

			public void mouseExited(MouseEvent arg0) {}
			

			public void mouseMoved(MouseEvent arg0) {}
	 
	
		
	}
	
	
}
```


----------



## Marco13 (25. Jun 2007)

Du hast da bei der Zeile mit den Fragezeichen
setLayer(layerLabel,0,1);   
aufgerufen. Das 'layerLabel' ist in dem Moment aber immer das LETZTE layerLabel, das in der Schleife erzeugt wurde. Eigentlich brauchst du dort aber das layerLabel, von dem das PopupMenu aufgerufen wurde. Das würde mit
setLayer(popup.getInvoker(),0,1);
gehen. Aber es bringt ja nichts, dort immer Layer '0' zu setzen. Spätestens nachdem alle Labels einmal nach oben bewegt wurden, liegen sie alle auf Layer 0, und dann geht (abgesehen von der 'position') garnichts mehr.

Ich habe mal den Code so verändert, dass die Labels anzeigen, auf welcher Layer (und Position) sie liegen. Du kannst dir ja mal ansehen, was bei deiner Ursprünglichen Lösung dort genau passiert ist. Aber auf so eine Idee solltest du auch kommen können: Irgendwelche Debug-Ausgaben einzubauen! Wenn du z.B. nur eine Zeile

*System.out.println("Setze layer 0 für Label mit farbe "+layerLabel.getBackground());*
setLayer(layerLabel,0,1);   

eingebaut hättest, hättest du schon gesehen, dass das immer das gleiche (falsche) ist!

Aber ich muß zugeben, dass dieses Layer-Handling dann doch etwas ekliger war, als ich zuerst vermutet hatte. Darum habe ich mal zwei praktische, "semi-spohisticated"-Hilfs-Methoden gebastelt, mit denen man eine komplette Layer nach oben- bzw. unten bewegen kann. Das "vernünftig" zu machen (z.B. so, dass die Positionen immer stimmen, und man nicht die Layer beliebig erhöhen oder verringern kann) war ein bißchen fummelig, scheint aber jetzt so weit zu funktionieren...


```
import java.awt.Color;
import java.awt.Dimension;
import java.awt.*;
import java.util.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;


public class LayeredPaneTest extends JLayeredPane {

   ArrayList<DragableLabel> labels = new ArrayList<DragableLabel>();
   DragableLabel layerLabel;
   Color [] background = {Color.GREEN, Color.BLUE, Color.WHITE, Color.BLACK, Color.GRAY};
   JPopupMenu popup;
   JMenuItem moveOneBehind, moveOneBefore;

   public LayeredPaneTest() {

      initPopupMenu();

      layerLabel = new DragableLabel();
      labels.add(layerLabel);
      layerLabel.setText("");
      layerLabel.setBorder(new LineBorder(Color.BLACK));
      layerLabel.setBackground(Color.MAGENTA);
      layerLabel.setBounds(2+(2*100),2+(2*100),210,210);
      add(layerLabel, new Integer(2));

      for(int i = 0;i<5;i++) {
        layerLabel = new DragableLabel();
        labels.add(layerLabel);
        layerLabel.setText("");
        layerLabel.setBorder(new LineBorder(Color.BLACK));
        layerLabel.setBackground(background[i]);
        layerLabel.setBounds(i+(i*100),i+(i*100),180,180);
        this.add(layerLabel, new Integer(i));
        updateLabels();
      }

      //ActionListener für PopupMenu,Layer index soll verändert werden
      moveOneBefore.addActionListener(new ActionListener() {

         public void actionPerformed(ActionEvent e){

            //setLayer(layerLabel,0,1);
            moveUp(popup.getInvoker());

            updateLabels();
         }
      });

      moveOneBehind.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e){
            moveDown(popup.getInvoker());
            updateLabels();
         }
      });
   }

   private void updateLabels()
   {
       for (int i=0; i<labels.size(); i++)
       {
           int layer = getLayer(labels.get(i));
           int pos = getPosition(labels.get(i));
           labels.get(i).setText("Layer: "+layer+" pos "+pos);
       }
   }




   //---------------------------------------------------------- Marco13 --->
   private void moveDown(Component component)
   {
       int currentLayer = getLayer(component);
       Component currentLayerComponents[] = getComponentsInLayer(currentLayer);
       int minLayer = lowestLayer();
       int nextLayer = currentLayer-1;
       while (nextLayer>=minLayer)
       {
           Component nextLayerComponents[] = getComponentsInLayer(nextLayer);
           if (nextLayerComponents.length != 0)
           {
               changeLayer(nextLayerComponents, currentLayer-nextLayer);
               break;
           }
           nextLayer--;
       }
       if (nextLayer >= minLayer)
       {
           changeLayer(currentLayerComponents, -1);
       }
   }

   private void moveUp(Component component)
   {
       int currentLayer = getLayer(component);
       Component currentLayerComponents[] = getComponentsInLayer(currentLayer);
       int maxLayer = highestLayer();
       int nextLayer = currentLayer+1;
       while (nextLayer<=maxLayer)
       {
           Component nextLayerComponents[] = getComponentsInLayer(nextLayer);
           if (nextLayerComponents.length != 0)
           {
               changeLayer(nextLayerComponents, currentLayer-nextLayer);
               break;
           }
           nextLayer++;
       }
       if (nextLayer <= maxLayer)
       {
           changeLayer(currentLayerComponents, 1);
       }
   }

    private void changeLayer(Component components[], int layerDelta)
    {
        int positions[] = new int[components.length];
        for (int i=0; i<components.length; i++)
        {
            positions[i] = getPosition(components[i]);
        }
        for (int i=0; i<components.length; i++)
        {
            setLayer(components[i], getLayer(components[i])+layerDelta);
        }
        for (int i=0; i<components.length; i++)
        {
            setPosition(components[i], positions[i]);
        }
    }
   //---------------------------------------------------------- Marco13 <---













   public void initPopupMenu(){

      moveOneBehind = new JMenuItem("Eine Ebene nach hinten");
       moveOneBefore = new JMenuItem("eine ebene nach vorne");
       popup = new JPopupMenu();
       popup.add(moveOneBefore);
       popup.add(moveOneBehind);
   }

   public static void main(String args []){

      JFrame f = new JFrame();
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.setContentPane(new LayeredPaneTest());
      f.setSize(new Dimension(700,700));
       f.setLocationRelativeTo(null);
       f.setTitle("Layer Test :-)");
      f.setVisible(true);
   }

   /**
    * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    * Code stammt teilweise von
    * [url]http://www.dpunkt.de/java/Programmieren_mit_Java/Oberflaechenprogrammierung/18.html[/url]
    *
    *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    */
   class DragableLabel extends JLabel implements MouseListener, MouseMotionListener {

       int startPoint = 0;
       int originalLayer;
       Point offsetPoint = null;

       DragableLabel() {

         setHorizontalAlignment(SwingConstants.CENTER);
         setOpaque(true);
         startPoint += 20;
         setBounds(startPoint, startPoint, 50, 50);
         addMouseListener(this);
         addMouseMotionListener(this);
       }

       public void mouseReleased(MouseEvent e){

          if(e.getButton() == MouseEvent.BUTTON3) {
              popup.show(DragableLabel.this,e.getX(),e.getY());
          }

       }

       public void mousePressed(MouseEvent e) {
         offsetPoint = new Point (e.getPoint ().x,e.getPoint ().y);

       }

       public void mouseDragged(MouseEvent e){
         if (offsetPoint != null)
          setLocation (getX () + (e.getX () - offsetPoint.x),getY () + (e.getY () - offsetPoint.y));

       }

         public void mouseClicked(MouseEvent arg0) {}

         public void mouseEntered(MouseEvent arg0) {}


         public void mouseExited(MouseEvent arg0) {}


         public void mouseMoved(MouseEvent arg0) {}



   }


}
```


----------



## Bernie (25. Jun 2007)

Oh mann...

ich glaube so langsam aber sicher raff ich das. Dachte mir schon, dass man das etwas weiter "ausprogrammieren" muss, um dieses Verhalten zu erreichen. Diese Sache mit Layer Index und Layerposition hat mich auch total verwirrt. Konsolen Prints hab ich etliche gemacht, aber manchmal sollte man halt einfach aufhören, wenn man merkt es geht gar nichts mehr. 
Dennoch, ich danke dir natürlich vielmals für deine Mühen.
Kleine Spende gefällig ?

Beste Grüße


----------



## Bernie (25. Jun 2007)

Oh mann...

ich glaube so langsam aber sicher raff ich das. Dachte mir schon, dass man das etwas weiter "ausprogrammieren" muss, um dieses Verhalten zu erreichen. Diese Sache mit Layer Index und Layerposition hat mich auch total verwirrt. Konsolen Prints hab ich etliche gemacht, aber manchmal sollte man halt einfach aufhören, wenn man merkt es geht gar nichts mehr. 
Wie auch immer,  ich danke dir natürlich vielmals für deine Mühen.
Kleine Spende gefällig ?

Beste Grüße


----------

