# Probleme mit setAlignmentX/Y



## shiny_hair (16. Apr 2006)

Hallo,

ich habe ein Problem mit setAlignmentX.
Folgende Situation: 
Ich habe ein JLayeredPane mit GridBagLayout, wo ich ein JPanel hinzufüge. Nun möchte ich ein Bild welches ich auf das JPanel platziere zentrieren per setAlignmentX bzw. setAlignmentY (z.B. setAlignmentY(Panel.CENTER) oder setAlignmentY(0.5f)).
Die Methoden haben allerdings keine Auswirkung. Der Debugger zeigt aber beim JPanel geänderte Werte an für das X/Y-Alignment.

Woran könnte das liegen?

Habe auch schon mit Layouts, die ich dem JPanel hinzufüge rumgespielt oder statt nem JPanel ein JLabel zu nehmen. Dies hat andere Alignment-Methoden, ich glaube setHorizontalAlignment und setVerticalAlignment.

Es ist zum verzweifeln. Es scheint so einfach zu sein und trotzdem funktioniert es nicht.

Gruß
Michael


----------



## André Uhres (16. Apr 2006)

Setz das JPanel mit dem Bild zuerst in ein JPanel mit GridBagLayout, das zentriert automatisch.


----------



## shiny_hair (16. Apr 2006)

Danke für die schnelle Antwort.

Hab gerade nochmals nachgeschaut wie ich das gemacht hab: tatsächlich ist es etwas anders gemacht wie zuerst beschrieben habe.
Ich platziere das JPanel (quasi die Leinwand) in das JLayeredPane (GridBagLayout) und wenn ich nen Actionlistener auslöse, wird ein neues, erweitertes JPanel (mit paintComponent/drawImage(BufferedImage, usw)), welches das Bild beinhaltet in das vorhandene "Leinwand"-JPanel hinzugefügt. 
An dem "Leinwand"-JPanel hab ich mich bisher vergebens ausgetobt mit setAlignmentX/Y, Layouts usw. 

Oder meinst du, daß ich das zu umständlich mache. Sollte ich das "Leinwand"-JPanel weglassen und sofort das JPanel mit dem Bild ins JLayeredPane einfügen?! Allerdings hab ich, wenn ich das Programm starte noch kein Bild parat. Dies wird erst durch eine Aktion bzw. ActionListener eingeleitet.


----------



## André Uhres (17. Apr 2006)

Was ich eigentlich sagen wollte: 
Dem *Leinwand-Panel* gibst du ein *GridBagLayout*.
Und das Leinwand-Panel kommt in das Hauptpanel, das ist dein jetziges JLayeredPane
(das JLayeredPane kannst du aber imho durch ein einfaches JPanel ersetzen).
Das Bild-Panel kommt dann in das Leinwand-Panel, ohne gridBagConstraints.
Dann ist dein Bild auf der Leinwand zentriert:

```
leinwand = new JPanel(new GridBagLayout());
        mainPanel.add(leinwand, gridBagConstraints);
...
        leinwand.add(bild);
```


----------



## shiny_hair (17. Apr 2006)

Hallo André,

ich habe mich wieder etwas verwirrend ausgedrückt. Da ich kein Freund davon bin hier zig Zeilen Code zu posten, hier die Visualisierung:





Alle Flächen, die man hier sieht sind, auf einem JLayeredPane platziert. Dieses JLayeredPane hat ein GridBagLayout. Also die farbigen Flächen sind per GridBagConstraints platziert. Das gelbe Feld links oben und der Hauptbereich rechts sind die Problemfelder (beides JPanel). Wenn ich dort nun ein neues JPanel mit dem Bild hinzufüge, dann sind die Bilder nach rechts verschoben. Scheinbar wird hierbei nur der 0, 0 Punkt zentriert.
In diesem Screenshot sind das Bild und das Thumbnail bereits vertikal von Haus aus zentriert. Allerdings gab es Probleme wenn ich über diese Ebene eine JPanel darübersetzte: es änderten sich die Breiten zwischen dem Hauptbereich, wo das Bild platziert wird und dem Randbereich, wo Auswahl und Thumbnail sind. Das lag daran, daß ich die Größe des erweiterten JPanels gemäß dem Thumbnail anzupassen versuchte. Diese Zeile war der Auslöser für die Breitenänderung:
bildpanel.setPreferredSize(new Dimension(album.getmyThumb().getWidth(), album.getmyThumb().getHeight()));
*album.getmyThumb* lierfert das BufferedImage/Thumbnail.
*bildpanel* ist das erweiterte JPanel worauf das BufferedImage (album.getmyThumb) per paintComponent platziert wird.
Lange Rede, kurzer Sinn: ich mußte das ganze umschreiben und wollte die Geschichte ganz locker per setAlignmentX/Y zentrieren. Hier mein Ansatz: 
	
	
	
	





```
bildpanel = new myJPanel(album.getmyThumb());
					oben.setAlignmentX(Component.LEFT_ALIGNMENT);
					oben.setAlignmentY(Component.CENTER_ALIGNMENT);
					oben.add(bildpanel);
					oben.validate();
```

Gruß
Michael


----------



## André Uhres (17. Apr 2006)

Dem Screenshot nach funktioniert das Zentrieren,
obschon mir nicht klar ist wie du das gemacht hast.
Wieso du danach Probleme hast bleibt mir gleichfalls schleierhaft.


----------



## shiny_hair (17. Apr 2006)

Der Screenshot wurde auch vor Erkennen des Problems gemacht. Aktuell sieht es so aus:




Hier das komplette Programm:
	
	
	
	





```
import java.io.*;
import java.util.Iterator;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.Graphics;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.*;

import java.net.*;

public class Test extends JApplet {


	Grafik myGrafik;
	
	public void init () {

		setSize(890, 490); 
		myGrafik = new Grafik(this.getContentPane());
		myGrafik.startGrafik();
	}
}


class Grafik extends JFrame {
	
	
	Container mycontainer = new Container();
	BilderBuffern album = new BilderBuffern();
	myLayer myframeinhalt = new myLayer();
	
	public Grafik(Container appletcontentpane) {
		mycontainer = appletcontentpane;
	}
		
	public void startGrafik() {
		mycontainer.add(myframeinhalt);
	}
	
	class myLayer extends JLayeredPane {
		

		GridBagLayout mylayout = new GridBagLayout();
		GridBagConstraints mycons = new GridBagConstraints();
		Ordner myOrdner;
		JMenuBar mybar = new JMenuBar();
		JMenu mymenu = new JMenu("Menue");
		JMenuItem mymenuitem = new JMenuItem("Ueber...");
		JPanel oben = new JPanel(); //fuer Bildvorschau
		JPanel wahl = new JPanel(); //ComboBox fuer Ordnerwahl
		JComboBox wahlbox = new JComboBox();
		JList mitte = new JList(); //fuer Bildliste
		JScrollPane mittescroll = new JScrollPane(mitte); //zum Scrollen der JList
		JButton unten = new JButton(); //vor-/zurueck-Buttons
		JPanel flaeche = new JPanel(); //Bildflaeche
		
		int helfer = 9999999; //Kruecke/Helfer-Variable, damit mouseover nicht unnoetig oft aufgerufen wird
		
		public myLayer() {
			this.setLayout(new GridBagLayout());
			myOrdner = new Ordner(); //Liste der verfuegbaren Bilder holen
			basisFlaeche();
		}
		
		public void basisFlaeche() {
		
		
			mymenuitem.addMouseListener(new menuListener());
			mymenu.add(mymenuitem);
			mybar.add(mymenu);
			wahlbox = new JComboBox(myOrdner.getOrdnerListe());
			wahlbox.addItemListener(new mausWahl());

			mitte.addMouseMotionListener(new mausEreignisse());
			mitte.addMouseListener(new mausEreignisse2());
			mitte.setListData(myOrdner.getDateiListe(0));
			mittescroll.setPreferredSize(new Dimension(30, 250));
						
			oben.setBackground(Color.YELLOW);
			wahl.setBackground(Color.CYAN);
			mitte.setBackground(Color.GREEN);
			unten.setBackground(Color.BLUE);
			flaeche.setBackground(Color.RED);
			
			gridbagHelfer(0, 0, 1, 1, 0.1, 0.01, 0, mybar, 1);
			gridbagHelfer(0, 1, 1, 1, 0.1, 0.5, 0, oben, 1);
			gridbagHelfer(0, 2, 1, 1, 0.1, 0.01, 0, wahl, 1);
			gridbagHelfer(0, 3, 1, 1, 0.1, 0.39, 0, mittescroll, 1);
			gridbagHelfer(0, 4, 1, 1, 0.1, 0.1, 0, unten, 1);
			gridbagHelfer(1, 0, 1, 5, 0.9, 1, 0, flaeche, 1);		
			wahl.add(wahlbox);
		}
		
		BorderLayout myborder = new BorderLayout(10, 10);
		myPopupJPanel testflaeche = new myPopupJPanel();
		JButton popupbutton = new JButton("Schliessen");
		
		public void popUp() {
			testflaeche.setOpaque(false);
			testflaeche.setLayout(myborder);
			gridbagHelfer(0, 0, 2, 5, 1, 1, 20, testflaeche, 400);
			this.setLayer(testflaeche, new Integer(400));
			testflaeche.add(popupbutton, BorderLayout.SOUTH);							
			this.validate();
		}
		
		//Hilfsmethode fuer GridBagLayout
		private void gridbagHelfer(int _gridx, int _gridy, int _gridwidth, int _gridheight, double _weightx, double _weighty, int _insets, JComponent komponente, int layerwert) {
			mycons.gridx = _gridx; //welche Stelle beginnt Zelle (x-Achse)
			mycons.gridy = _gridy; //welche Stelle beginnt Zelle (y-Achse)
			mycons.gridwidth = _gridwidth; //ueber wieviel Felder ragt die Zelle (x-Achse)
			mycons.gridheight = _gridheight; //ueber wieviel Felder ragt die Zelle (y-Achse)
			mycons.weightx = _weightx; //die Gewichtung relativ zu den anderen Zellen (x-Achse)
			mycons.weighty = _weighty; //die Gewichtung relativ zu den anderen Zellen (y-Achse)
			mycons.insets = new Insets(_insets, _insets, _insets, _insets);
			mycons.fill = GridBagConstraints.BOTH; //der restliche Platz wird mit Komponente gefuellt	
			
			this.addImpl(komponente, mycons, layerwert); //addImpl notwendig wegen Constraints
			this.setLayer(komponente, new Integer(layerwert));
		}	
		

		//Extra-Klasse fuer JPanel wegen paintComponent
		public class myJPanel extends JPanel {
			
			private static final long serialVersionUID = 3539041744270282816L;
			BufferedImage puffbild;
			BufferedImageOp myop;
			
			public myJPanel(BufferedImage bufferimage) {
				puffbild = bufferimage;
				this.setBounds(0, 0, puffbild.getWidth(),puffbild.getHeight()); //loeschen
			}
			
			public void paintComponent (Graphics g) {
				super.paintComponent(g);
				Graphics2D g2d = (Graphics2D) g;
				g2d.setClip(0 ,0, puffbild.getWidth(), puffbild.getHeight());
				g2d.drawImage(puffbild, null, 0, 0);
			}	
		}
		
		//Extra-Klasse (halbtransparent) fuer Popup-JPanel wegen paintComponent
		public class myPopupJPanel extends JPanel {
			
			private static final long serialVersionUID = 8782249918175277703L;
		
			public myPopupJPanel() {
		
			}
			
			public void paintComponent (Graphics g) {
				super.paintComponent(g);
				Graphics2D g2d = (Graphics2D) g;
				g2d.setColor(new Color(3, 65, 27, 210));
				g2d.fill3DRect(0, 0, 850, 450, true);
			}	
		}
		
		//fuer Ordnerauswahl-Box
		private class mausWahl implements ItemListener {
		
			public void itemStateChanged (ItemEvent event) {
				mitte.setListData(myOrdner.getDateiListe(wahlbox.getSelectedIndex()));	
			}
		}
		
		//fuer Menue
		private class menuListener extends MouseAdapter {
		
			public void mousePressed(MouseEvent event) {
				myframeinhalt.popUp();
			}
			
		}
		
		myJPanel bildpanel;
		
		
		//fuer Rollover
		private class mausEreignisse extends MouseMotionAdapter {
			
			int drueberindex;
			
			public void mouseMoved (MouseEvent event) {
				drueberindex = mitte.locationToIndex(event.getPoint());
				if (helfer != drueberindex) {
					mitte.setSelectedIndex(drueberindex);
					mitte.setSelectionBackground(Color.WHITE);
					helfer = drueberindex;
					System.out.println(drueberindex);
					
					album.thumbnailLaden(myOrdner.getgewaehltesBild(wahlbox.getSelectedIndex(), mitte.locationToIndex(event.getPoint())));	
					oben.removeAll();
					oben.repaint();
					bildpanel = new myJPanel(album.getmyThumb());
				//	bildpanel.setPreferredSize(new Dimension(album.getmyThumb().getWidth(), album.getmyThumb().getHeight()));
               oben.setAlignmentX(Component.LEFT_ALIGNMENT);
					oben.setAlignmentY(Component.CENTER_ALIGNMENT);
					oben.add(bildpanel);

					oben.validate();
					
				}
			}
	}

		//fuer Klick
		private class mausEreignisse2 extends MouseAdapter {
			
			public void mouseClicked(MouseEvent event) {
				album.bilderLaden(myOrdner.getgewaehltesBild(wahlbox.getSelectedIndex(), mitte.locationToIndex(event.getPoint())));	
				flaeche.removeAll();
				flaeche.setAlignmentX(0.3f);
				flaeche.setAlignmentY(0.3f);
				flaeche.repaint();
				myJPanel nu = new myJPanel(album.getmyBuffer());
			//	nu.setPreferredSize(new Dimension(album.getmyBuffer().getWidth(), album.getmyBuffer().getHeight()));
				nu.setAlignmentX(Component.LEFT_ALIGNMENT);
				nu.setAlignmentY(Component.CENTER_ALIGNMENT);
				flaeche.add(nu);
				flaeche.validate();
			}		
		}		
	}
}

class Ordner {

	//Fuer Ordner
	File ordnerinhalt;
	String[] ordnerliste;
	
	//Fuer Bilddateien
    String pfad = "/home/michlmann/Test/";
	File pfadinhalt;
	//fuer JList Liste ersetellen
	String[] bildliste;
	//zum Aufruf der Bilddaten
	String hilfsvar;
	String[] bildpfad;
	
	
	public Ordner() {	
		ordnerinhalt = new File(pfad);
	}
	
	
	
	public String[] getOrdnerListe() {
		ordnerliste = ordnerinhalt.list();
		return ordnerliste;
	}
	
	public String[] getDateiListe(int gewaehlterordner){
		pfadinhalt = new File(pfad + ordnerliste[gewaehlterordner]);
		bildliste = pfadinhalt.list();
		for (int i=0; i < bildliste.length; i++) {
			//.jpg abschneiden
			bildliste[i] = bildliste[i].substring(0, bildliste[i].length()-4);
		}
		return bildliste;
	}
	
	//gibt ausgewaehlte Datei (Text + jpg) + Pfad zurueck
	public String getgewaehltesBild(int ordnerlistwert, int bildlistwert) {
		String rueck = pfad + ordnerliste[ordnerlistwert] + "/" + bildliste[bildlistwert] + ".jpg";
		return rueck;
	} 
	
}


class BilderBuffern  {
	
	URI myuri;
	Iterator readeriterator;
	ImageReader myreader;
	ImageInputStream myinstream;
	BufferedImage mybuffer;
	Graphics mygraphics;

	IIOImage myio;
	
	ImageOutputStream myoutstream;
	BufferedImage mythumbnail;
	
	public BilderBuffern() {
		readeriterator = ImageIO.getImageReadersBySuffix("jpg");
		myreader = (ImageReader)readeriterator.next();
	}
	
	public void bilderLaden(String gewaehltesbild) {
		
		try {
			myinstream = ImageIO.createImageInputStream(new File(gewaehltesbild));
			myreader.setInput(myinstream, false);
			mybuffer = myreader.read(0);
		} catch (IOException e) {
			System.err.println("Ein-/Ausgabeproblem.");
		} catch (IllegalArgumentException e) {
			System.err.println("Streamproblem.");
		} 
	} 
	
	//alle Thumbnails laden
	public void thumbnailLaden(String gewaehltesbild) {
		
		try {
			ImageReadParam myparam = new ImageReadParam();
			myinstream = ImageIO.createImageInputStream(new File(gewaehltesbild));
			myreader.setInput(myinstream, false);
			myparam = myreader.getDefaultReadParam();
			myparam.setSourceSubsampling(6, 6, 0, 0);
			mythumbnail = myreader.read(0, myparam);

				
			} catch (IOException e) {
				System.err.println("Ein-/Ausgabeproblem.");	
			} catch (UnsupportedOperationException e) {
				System.err.println("Nicht unterstuetzte Operation.");
			} catch (IllegalStateException  e) {
				System.err.println("Keine Eingabequelle gesetzt.");
			} catch (IndexOutOfBoundsException e) {
				System.err.println("Index ausserhalb.");
			} 
		}
	
	
	public BufferedImage getmyBuffer() {
		return mybuffer;
	}	
	
	public BufferedImage getmyThumb() {
		return mythumbnail;
	}
}
```
Zeile 204 bzw. 225 bewirken zwar ne horizontale Zentrierung, wie du sie auf dem Screenshot siehts, wirken sich aber ungünstig auf das gesamte Layout aus, sobald ich *Menue/Ueber* aufrufe und ein JPanel über der vorhandenen Ebene platziert wird. 
Wenn ich die beiden Zeilen entferne, dann verändert es zwar nicht mehr mein Layout, aber dafür sind die Bilder nicht zentriert.
_
Wer den Code testen möchte, sollte beachten, daß er unter /home/<user>/Test/ ein Verzeichnis anlegt mit jpg-Dateien (nicht jpeg) drin und Zeile 240 entsprechend anpasst._


----------



## André Uhres (17. Apr 2006)

Jedes JPanel sollte eine PreferredSize haben.
Man kann dazu auch _getPreferredSize()_ überschreiben.
Zum Beispiel:

```
...
      public class myJPanel extends JPanel { 
...
         public Dimension getPreferredSize(){
             return new Dimension(puffbild.getWidth(), puffbild.getHeight());
         }
...
      } 
...
```
Btw: wenn ich Menue->Ueber wähle tut sich nicht sehr viel.


----------



## shiny_hair (17. Apr 2006)

André Uhres hat gesagt.:
			
		

> Btw: wenn ich Menue->Ueber wähle tut sich nicht sehr viel.


Dürfte eigentlich nur ein halbdurchsichtiges JPanel erscheinen mit einem Schließen Button der nicht funktioniert. -> Ist noch in der Entwicklung  :wink:
Oder meintest du bezüglich der darunterliegenden Ebene? Falls ja, schalte Zeile 204 und 225 ein, rufe ein Bild auf und gehe dann nochmals auf Menue/Ueber.


----------



## André Uhres (18. Apr 2006)

Wie gesagt: das PreferredSize muss schon sein.
Und das Layout kannst du ja mit _weighty einstellen.


----------



## shiny_hair (18. Apr 2006)

Werde ich heute Abend mal testen.
Trotzdem würde mich interessieren, weshalb setAlignmentX/Y keine Auswirkung hat...
Liegt das vielleicht daran, daß ich auf dem JLayeredPane ein GridBagLayout benutze?


----------



## shiny_hair (18. Apr 2006)

André Uhres hat gesagt.:
			
		

> Wie gesagt: das PreferredSize muss schon sein.


Das ist der springende Punkt! Ich habe den ganzen JPanels, die ich ins Layout reinbring, kein PreferredSize zugewiesen, sondern allein über das GridBagLayout die Größe bestimmt.
Nun kann ich auch wieder die Zeilen 204 und 225 benutzen, ohne daß es das Layout mehr verhaut. 

Die Bilder sind nun wieder horizontal zentriert. Wie bekomm ich aber nun auch eine vertikale Zentrierung hin?!
setAlignmentX/Y scheint ne Totgeburt zu sein. Damit klappt überhaupt nix obgleich es so einfach aussieht. Was hab ich übersehen, wo ist der Haken?


----------

