# JFrame JPanelgrösse fixieren Bild darin skalieren



## Ongbak (7. Apr 2007)

Hallo,

Langsam bin ich verzweifelt. Ich habe zwar schon dieverse Forumsbeiträge gelesen, aber bin nie richtig schlauf daraus geworden. 
So ungefähr soll das Layout aussehen:

111111122
111111122
111111122
111111122
333333333

Die 1sen ist das JPanel mit dem ich Probleme habe, die 2en und 3en wären andere JPanels die aber noch nicht drinn sind.
Ein JFrame hält alles zusammen.

Was ich gerne möchte. Das JPanel soll in diesem dargestellten Verhältniss erstellt werden und genau so gross sein.
Das Bild darf nur in diesem JPanel in dieser Grösse dargestellte werden.

Probleme. Wenn ich in meinem BorderLayout

```
add(spielbrett);
```
eingebe, dann zeigt wird das Fenster eröffnet, aber das Bild ist grösser als geplant, bzw. das JPanel passt sich dem Bild an anstatt umgekehrt.


```
add("West",spielbrett);
```
bei dem wird zwar das Fenster erstellt, aber das Bild ist weg.


```
scaledspielbrett = spielbrett.getScaledInstance(spielBrettBreite,spielBrettHoehe,Image.SCALE_FAST);
```
Bei dem hier hat er OutOfMemory Probleme, obwohl das bild nur 1117*861 gross ist, ich auf meinem Rechner 1GB im dual channel betrieb habe, das kanns ja echt nicht sein.

Eine weitere Frage: Ist BorderLayout eine gute Wahl für mein Designvorhaben, oder ist das ein Fehlgriff?
Bestimmt der Layoutmanager die grösse des JPanels oder wie sind hier die Wechselwirkungen?

Hier noch der ganze relevante Code:

```
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

/*
 * GUI Klasse für die Darstellung des gesamten Spielbrettes
 * inklusive den Bedienelementen.
 * Verwaltet alle primären Panels zur Grafikausgabe
 */

public class ThurnNTaxisGUI extends JFrame
{
	private CGUIDaten aktGUI;	//speichert und stellt Grafikinfos bereit.
	private CSpielbrett spielbrett; //JPanel um Spielbrett anzuzeigen
	private int fensterHoehe;	//Speichert Hoehe des Gesamtfensters
	private int fensterBreite;	//Speichert Breite des Gesamtfensters
	public ThurnNTaxisGUI(String titel)
	{
		super(titel);
		
		//Initialisierung von aktGUI
		aktGUI = new CGUIDaten();
		
		//setzt alle Koordinaten auf 0, Startoption
		aktGUI.setXPos(0);
		aktGUI.setYPos(0);
		aktGUI.setBildX1(0);
		aktGUI.setBildX2(0);
		aktGUI.setBildY1(0);
		aktGUI.setBildY2(0);
		
		//Maximiert Fenster über ganzer Desktop
		setExtendedState(this.MAXIMIZED_BOTH);
		
		//Initialisierung des LayoutManagers für die Anordnung der Primären Panels
		setLayout(new BorderLayout());
		
		//Initialisieren des SpielbrettPanels
		//Übergibt 3 Parameter: GUIDatenbank,aktuelle Fensterhöhe,aktuelle fensterBreite
		spielbrett = new CSpielbrett(aktGUI,this);
		add(spielbrett);
		
		//Bei Befehl Fensterschliessen wird Fenster ohne Rückmeldung
		//an den user, gesclossen!!!
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		
	}
	public int getFensterBreite() {
		fensterBreite = getHeight();
		return fensterBreite;
	}
	public void setFensterBreite(int fensterBreite) {
		this.fensterBreite = fensterBreite;
	}
	public int getFensterHoehe() {
		fensterHoehe = getWidth();
		return fensterHoehe;
	}
	public void setFensterHoehe(int fensterHoehe) {
		this.fensterHoehe = fensterHoehe;
	}
}
```
Das JPanel noch:

```
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Dimension;
import java.awt.Graphics2D;

/*
 * Oberfläche zur Darstellung des Spielbrettes als Hintergrund
 * Keine aktive Aufgabe.
 * Skalliert bei Fenstergrössenänderung das Spielbrett korrekt
 */
public class CSpielbrett extends JPanel
{
	private ThurnNTaxisGUI hauptFenster; //Referenz auf das Hauptfenster
	private Image spielbrett;	//Speichert temporär die Bilddatei
	private Image scaledSpielBrett; //temporäres skalliertes Bild des Spielbretts
	private CGUIDaten aktGUI;	//Datei mit allen benötigten Daten
	private int spielBrettHoehe;	//Höhe des Spielbretts in Abängigkeit von Hauptfenster
	private int spielBrettBreite;	//Breite des Spielbretts in Abhängig. von Hauptfenster
	
	public CSpielbrett(CGUIDaten aktGUI,ThurnNTaxisGUI HauptFenster)
	{
		//abspeichern der GUI Datenbank
		this.aktGUI = aktGUI;
		
		//abspeichern der Hauptfensterreferenz
		hauptFenster = HauptFenster;
		
		//temporäre Bilddatei abspeichern
		spielbrett = aktGUI.getAktuellesSpielBrett();
	}
	
	public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		
		//Berechnet aktuelle Fenstergrösse
		setSpielBrettHoehe(hauptFenster.getFensterHoehe());
		setSpielBrettBreite(hauptFenster.getFensterBreite());
				
		if(spielbrett != null)
			g.drawImage(spielbrett,0,0,this);		
	}
	
	//Gibt die maximale grösse des Panels zurück
	public Dimension getMaximumSize()
	{
		Dimension tmp = new Dimension(spielBrettBreite,spielBrettHoehe);
		return tmp;
	}
	
	//Gibt die bevorzugte Panel grösse zurück
	public Dimension getPreferredSize()
	{
		return getMaximumSize();
	}
	
	public Dimension getMinimumSize()
	{
		return getMaximumSize();
	}

	public int getSpielBrettBreite() {
		return spielBrettBreite;
	}
	
	//@pre: Fensterbreite maximiertes Hauptfenster
	//@post: Transformation im Verhältnis 5/6 = JPanelbreite
	public void setSpielBrettBreite(int spielBrettBreite) {
		this.spielBrettBreite = ((spielBrettBreite/6)*5);
	}

	public int getSpielBrettHoehe() {
		return spielBrettHoehe;
	}

	//@pre: Fensterhöhe maximiertes Hauptfenster
	//@post: Transformation im Verhältnis 5/6 = JPanelhöhe
	public void setSpielBrettHoehe(int spielBrettHoehe) {
		this.spielBrettHoehe = ((spielBrettHoehe/6)*5);
	}
	
}
```
Ich habe alle Skalierung und Layoutbefehle wieder rausgenommen, waren eh nur 2 Zeilen code, weil dies ja falsch waren.

Ich danke jetzt schon für eure Hilfe

mfg


----------



## SlaterB (7. Apr 2007)

tja, das scheint tatsächlich zunächst nicht zu gehen,
wenn du zwei-drei Panel drin hast, dann werden die Size-Operationen vielleicht doch berücksichtigt,

für nur ein Panel bieten sich andere Layouts an, z.B. BoxLayout, wobei allerdings nicht unbedingt gleich die obere linke gewählt wird..


```
public class TestGUI extends JFrame {

	public TestGUI() throws Exception {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(800, 600);

		ImagePanel p = new ImagePanel();
		getContentPane().add(p);
		getContentPane().setLayout(
			new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
		setVisible(true);
	}

	public static void main(String[] args) throws Exception {
		TestGUI t = new TestGUI();
	}

	class ImagePanel extends JPanel {
		private Image image;

		public ImagePanel() {
			loadImage();
			setBorder(BorderFactory.createTitledBorder("ImagePanel"));
		}

		//Gibt die maximale grösse des Panels zurück
		public Dimension getMaximumSize() {
			Dimension tmp =
				new Dimension(
					image.getWidth(this) + 20,
					image.getHeight(this) + 30);
			return tmp;
		}

		//Gibt die bevorzugte Panel grösse zurück
		public Dimension getPreferredSize() {
			return getMaximumSize();
		}
		//Gibt die bevorzugte Panel grösse zurück
		public Dimension getSize() {
			return getMaximumSize();
		}
		public Dimension getMinimumSize() {
			return getMaximumSize();
		}

		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.drawImage(image, 10, 20, this);
		}

		public void loadImage() {
			MediaTracker tracker = new MediaTracker(this);
			image = Toolkit.getDefaultToolkit().getImage("test.jpg");
			tracker.addImage(image, 0);
			try {
				tracker.waitForID(0);
			} catch (InterruptedException exception) {
			}
		}

	}
}
```
GridBagLayout bietet von den StandardLayouts die meisten Möglichkeiten


----------



## Ongbak (7. Apr 2007)

So, ich habe die zwei anderen Panels noch hinzugefügt und die hintergrundfarbe einfach gsetzt, nur als Platzhalter, zum schauen ob die Panels in rot und blau auftauchen. Leider aber nein. Es taucht weiterhin der grösste Panel auf welches als einziger Panel ein Bild aufruft. Es ist als ob er die anderen Panels unterdürckt, obwohl ich allen genau die Grösstmögiche Grösse angegeben habe. ich weiss einfach nicht was ich falsch mache.

Hier nochmals der code des Hauptfensters:

```
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

/*
 * GUI Klasse für die Darstellung des gesamten Spielbrettes
 * inklusive den Bedienelementen.
 * Verwaltet alle primären Panels zur Grafikausgabe
 */

public class ThurnNTaxisGUI extends JFrame
{
	private CGUIDaten aktGUI;	//speichert und stellt Grafikinfos bereit.
	private CSpielbrett spielbrett; //JPanel um Spielbrett anzuzeigen
	private CSpielerTisch spielertisch; //JPanel für Spielerkarten und akt. Strasse
	private CGegnerTisch gegnertisch; //JPanel für die Zustände der Gegner
	private int fensterHoehe;	//Speichert Hoehe des Gesamtfensters
	private int fensterBreite;	//Speichert Breite des Gesamtfensters
	public ThurnNTaxisGUI(String titel)
	{
		super(titel);
		
		//Initialisierung von aktGUI
		aktGUI = new CGUIDaten();
		
		//setzt alle Koordinaten auf 0, Startoption
		aktGUI.setXPos(0);
		aktGUI.setYPos(0);
		aktGUI.setBildX1(0);
		aktGUI.setBildX2(0);
		aktGUI.setBildY1(0);
		aktGUI.setBildY2(0);
		
		//Maximiert Fenster über ganzer Desktop
		setExtendedState(this.MAXIMIZED_BOTH);
		
		//Initialisierung des LayoutManagers für die Anordnung der Primären Panels
		BorderLayout layout = new BorderLayout();
		setLayout(layout);
		
		//Initialisieren des SpielbrettPanels
		//Übergibt 3 Parameter: GUIDatenbank,aktuelle Fensterhöhe,aktuelle fensterBreite
		spielbrett = new CSpielbrett(aktGUI,this);
		add("Center",spielbrett);
		
		//Initialisierung des Spielbrettes
		spielertisch = new CSpielerTisch(aktGUI,this);
		add("South",spielertisch);
		
		//Initialisierung des Fenster für die Gegnerinformationen
		gegnertisch = new CGegnerTisch(aktGUI,this);
		add("West",gegnertisch);
		
		//Bei Befehl Fensterschliessen wird Fenster ohne Rückmeldung
		//an den user, gesclossen!!!
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		
	}
	public int getFensterBreite() {
		fensterBreite = getHeight();
		return fensterBreite;
	}
	public void setFensterBreite(int fensterBreite) {
		this.fensterBreite = fensterBreite;
	}
	public int getFensterHoehe() {
		fensterHoehe = getWidth();
		return fensterHoehe;
	}
	public void setFensterHoehe(int fensterHoehe) {
		this.fensterHoehe = fensterHoehe;
	}
}
```

und hier einfach der code eines der anderen zwei panels, sind ja beide fast identisch

```
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Dimension;

/*
 * Klasse stellt die aktuellen Karten die der Spieler hat dar
 * Stellt auch aktuelle Strasse dar
 * Angeordnet südlich von Spielbrett
 */
public class CSpielerTisch extends JPanel
{
	private CGUIDaten aktGUI;		//Referenz auf GUIDatenklasse
	private ThurnNTaxisGUI hauptFenster;	//Referenz auf Hauptfenster
	private int spielerTischHoehe;		//aktuelle Höhe 
	private int spielerTischBreite;	//akteulle Breite
	public CSpielerTisch(CGUIDaten guiData,ThurnNTaxisGUI HauptFenster)
	{
		aktGUI = guiData;
		hauptFenster = HauptFenster;
		setBackground(Color.BLUE);
	}
	
	public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		
		//Berechnung der aktuellen Fenstergrössen
		setSpielerTischBreite(hauptFenster.getFensterBreite());
		setSpielerTischHoehe(hauptFenster.getFensterHoehe());
	}
	
	//Definition von bevorzugten Panelgrössen
	public Dimension getMaximumSize()
	{
		Dimension tmp = new Dimension(spielerTischBreite,spielerTischHoehe);
		return tmp;
	}
	
	public Dimension getPreferredSize()
	{
		return getMaximumSize();
	}
	
	public Dimension getMinimumSize()
	{
		return getMaximumSize();
	}

	public int getSpielerTischBreite() {
		return spielerTischBreite;
	}

	public void setSpielerTischBreite(int spielerTischBreite) {
		this.spielerTischBreite = (spielerTischBreite);
	}

	public int getSpielerTischHoehe() {
		return spielerTischHoehe;
	}

	public void setSpielerTischHoehe(int spielerTischHoehe) {
		this.spielerTischHoehe = (spielerTischHoehe/6);
	}
}
```

Sieht irgendwer was ich da in den Sand gesetzt habe, code technisch?

mfg


----------

