LayoutManager Position der Componenten nachträglich ändern

wolfilein

Mitglied
Ich versuche momentan einen eigenen kleinen Layoutmanager zu schreiben, welcher eine Kordinatensystem erzeugt auf welchen man die Componenten dann plazieren kann und ihnen ihre größe zuweisen kann.Der Layoutmanger soll dies dann am ende immer an die aktuelle fenstergröße anpassen.
Mein Problem ist momentan, dass ich diese Eigenschaften später noch ändern will, zb das mann buttons verschieben oder ihre Größe ändern kann

//edit Lösung gefunden
ist relativ einfach zum nutzen 😉
Layout erstellen durch
setLayout(new CoordLayout(x,y)); //größe des Koordinatensystems bestimmen
und dann
.add(component,new prefBounds(x,y,w,h);//Position im system festlegen (mit float)

Java:
class CoordLayout implements LayoutManager2
{
	
	float x;
	float y;
	private HashMap<Component,prefBounds> components;
	public CoordLayout(float x,float y) {
	super();
	this.x=x;
    this.y=y;
    components = new HashMap<Component,prefBounds>();
	}
	    public void addLayoutComponent(Component comp, Object constraints){
	    	if (constraints instanceof prefBounds){
	    	components.put(comp,(prefBounds) constraints);
	    	}else {
	    		try {
					throw new missingRectangle("missing prefBounds");
				} catch (missingRectangle e) {
					e.printStackTrace();
				}
	    	}
	    }
	  	 
	    public void layoutContainer(Container parent)
	    {
	    	for (Component key :components.keySet()){
	    		prefBounds z =  components.get(key);
	    		float xfact = (float)parent.getWidth()/x;
	    		float yfact = (float)parent.getHeight()/y;
	    		key.setLocation((int)(xfact * z.x), (int) (yfact*z.y));
	    		key.setSize((int) (z.w*xfact), (int)(z.h*yfact));
	    		System.out.println(z.w);
	    	}
	    	  
	    }
	    public void removeLayoutComponent(Component comp)
	    {
	    	components.remove(comp); 
	    }
	    public Dimension preferredLayoutSize(Container parent)
	    {
	        return parent.getSize();
	    }
	    
	    public void invalidateLayout(Container target) {}
	    public void addLayoutComponent(String name, Component comp) {
	    	
	    }
	    
	    public float getLayoutAlignmentY(Container target) { return 0; }
	    public float getLayoutAlignmentX(Container target) { return 0; }
	    
	    public Dimension maximumLayoutSize(Container target) { return(preferredLayoutSize(target)); }
	    public Dimension minimumLayoutSize(Container parent) { return(preferredLayoutSize(parent)); }
	}
class missingRectangle
extends Exception
{
  public missingRectangle()
  {
		
  }
  public missingRectangle(String s)
  {
    super(s);	
  }
}
class prefBounds {
    float x;
    float y;
    float w;
    float h;
    public prefBounds(float x,float y,float w,float h){
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
    }
   
}
 
Zuletzt bearbeitet:
Quellcode in dem sinne gibst noch nicht ^^
das ganze soll für nen anderes Programm genutzt werden wo ich das momentan noch etwas unschön gelöst hab.
es hakelt an der Theorie
also das Layout hat später dann mal zb nen Koordinatensystem von 10,20 und ich setzt auf 4.5;5.5 einen Button der 1.0 hoch und weit ist.
den Button will ich dann später aber wo anders hin haben, und genau das ist mein Problem wie soll ich das Implementieren?
 
Ein wenig sehr wenig Informationen. Wie willst du die Koordinaten setzen? Per Constrain? Dann würde ich eine Wrapplerklasse schreiben, die den Comp und die Loc. speichert. Im Manager eine HashMap, die den Comp als Key mit dem Wrappler verknüpft. Beim Eintragen wird geschaut, ob der Comp schon gespeichert ist, wenn ja den Wrappler hohlen und die Position aktualisieren. Ansonst einen neuen erzeugen und Mappen.
 
den Button will ich dann später aber wo anders hin haben, und genau das ist mein Problem wie soll ich das Implementieren?
Was bedeutet "später .. wo anders hin haben". Der Anwender soll zur Laufzeit den Button verschieben könnnen? Wenn ja, dann muss man das selbst mittels Mouse- und MouseMotionListener selbst implementieren.
Oder das Layout soll durch ein Funktion eine andere Darstellung einnehmen, dann kann man dem Button und en anderen Komponenten ja einfach die neue Position zuweisen.
 
@Volvagia
ja genau das meinte ich ^^
du meinst also ich soll zum ändern später zum auch noch die add metode nutzen?
wär das dann aber nicht n bissel am Ziel vorbei ?
Und ich bin noch anfänger kannst du mir das mit den wraper klassen mal erklären (eher gesagt was der unterschiedzur normalen klasse ist)
@Michael
Die Sache mit dem MouseMotionListener ist schon implentiert nur momentan wird nen null layout genutzt wo sich jede compente selbst an die fenstergröße anpasst 😉
mal ne genauere Beschreibug:
Ich versuche grad eine art Zeitleiste zu programmieren, die einzelnen elemente dieser zeileiste sind buttons, der Rest wird gezeichnet.
Und genau hier liegt das Problem ich muss her relative genau sagen können wo sich das Objekt befindet,
(deshalb ein Koordinatensystem ) und es dann aber (zum sotieren und verschieben )
relativ pixelgenau bewegen können 😉
 
Zuletzt bearbeitet:
Einfach nur eine Klasse, die den Comp und die Position speichert. Wenn es sich um eine Zeitleiste handelt, würde ich nur ein Date-Objekt übergeben, und den LayoutManager die Position errechnen lassen, also nur noch mit add und remove von außen Änderungen vornehmen. Der Manager weiß ja, wie lang sein Parent ist, und kann so die Zeit gemäß einen Zeitraum (Tage, Monate, Jahre, Jahrtausende) die du per Konstruktor oder Setter setzt einteilen und die Comps so richtig nach ihren Date-Infos setzen.
 
@Volvagia
nee denn man wird das objeckt später auch noch vergrößern können 😉
aber schonmal vielen dank für deine Hilfe ich werds jetzt mal veruschen zu impentieren 😉
 
ok erstmal ein großes danke an Volvagia für deine Hilfe 😉
das Layout funktioniert ^^.
falls es jemand braucht hier mal der Code (mit main class zum testen)
Java:
public class CoordLayout implements LayoutManager2
{
	static public void main(String[] tt ){
		JFrame me = new JFrame("test");
		CoordLayout layout =  new CoordLayout(100,100);
		me.setLayout(layout);
		me.setSize(100,100);
		JButton Test = new JButton("test");
		me.add(Test,new prefBounds(5,5,1,1));
		//me.getLayout().
		me.add(Test,new prefBounds(7,5,10,1));
		//layout.addLayoutComponent(Test,new prefBounds(5,5,10,1));
		
		//layout.add(Test,new prefBounds(10,5,1,1));
		me.setVisible(true);
	}
	float x;
	float y;
	private HashMap<Component,Object> components;
	public CoordLayout(float x,float y) {
	super();
	this.x=x;
    this.y=y;
    components = new HashMap<Component,Object>();
	}
	    public void addLayoutComponent(Component comp, Object constraints){
	    
	    	components.put(comp,constraints);
	  
	    }
	  	 
	    public void layoutContainer(Container parent)
	    {
	    	for (Component key :components.keySet().toArray(new Component[0])){
	    		prefBounds z = (prefBounds) components.get(key);
	    		float xfact = (float)parent.getWidth()/x;
	    		float yfact = (float)parent.getHeight()/y;
	    		key.setLocation((int)(xfact * z.x), (int) (yfact*z.y));
	    		key.setSize((int) (z.w*xfact), (int)(z.h*yfact));
	    	}
	    	  
	    }
	    public void removeLayoutComponent(Component comp)
	    {
	    	components.remove(comp); 
	    }
	    public Dimension preferredLayoutSize(Container parent)
	    {
	        return null;
	    }
	    
	    public void invalidateLayout(Container target) {}
	    public void addLayoutComponent(String name, Component comp) {
	    	
	    }
	    
	    public float getLayoutAlignmentY(Container target) { return 0; }
	    public float getLayoutAlignmentX(Container target) { return 0; }
	    
	    public Dimension maximumLayoutSize(Container target) { return(preferredLayoutSize(target)); }
	    public Dimension minimumLayoutSize(Container parent) { return(preferredLayoutSize(parent)); }
	}

class prefBounds {
	float x;
	float y;
	float w;
	float h;
	public prefBounds(int x,int y,int w,int h){
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
	}
}
ein Problem habe ich aber noch 😉
wie nutze ich das jetzt in verbindung mit ner scrollbar 😉
 
Zuletzt bearbeitet:
Nach dem das Layout ja über den ganzen Parent verteilt wird, würde ich einfach parent.getSize als PreferredSize zurückgeben.

Ich würde statt prefBounds einfach ein Rectangle übergeben, das ist einfach gewöhnlicher als eine eigene Klasse. Dann würde ich noch im add... per instanceof prüfen, ob es sich um ein gültiges Constraint handelt und eine eigene Exception schmeißen, bevor im layout... eine ClassCastException fliegt. Dann kannst du es auch direkt gecastet speichern und hältst das aus den vergleichsweiße komplizierten layout... raus. Und das Set von HashMap#keySet kann direkt iteriert werden, du musst es nicht jedes mal in ein Array konvertieren.

Aber echt nice, dass du das so schnell runtergeschrieben hast. Für mathematiche Wege muss ich immer ein wenig überlegen. 😳
 
ok Danke 😉
ich setzt das Thema mal als gelöst ^^
und Mathematik ist kein Problem nur Programmieren kann manchmal echt kompliziert werden 😉

und ich finde das Layout sehr einfach zu benutzen ist wohl Geschmacksache 😀.
und das mit den prefBounds liegt daran das ich auch dezimalzahlen nutzen möchte.
 
Zuletzt bearbeitet:

Zurück
Oben