# JPanel Überschreiben // paintComponent?



## watsefaq (29. Nov 2011)

Guten Abend,

mein eigentliches Problem ist, dass ich vorhabe einen Baum zu malen und dann als Bild abzuspeichern. Dieser Baum basiert auf Datensätzen, welche ich aus einer Datenbank hole. Diese repräsentieren einen Stammbaum und können somit beliebig weit nach unten gehen.

Meine ersten Ideen in der Richtung sind leider fehlgeschlagen, weswegen ich jetzt eine Unterklasse von JPanel geschrieben habe, welche mir das ganze erledigt. Später wird das ganze von einer Hilfsklasse gespeichert. In der Theorie funktioniert das ganze auch ...

Nun zu der Frage bzw. dem Problem:
Ich habe versucht paintComponent zu schreiben um dort den Wurzelknoten des Baumes zu malen. Danach dachte ich mir, könne ich das ganze einfach rekursiv machen um keinen Knoten zu vergessen. 

Folgenden Quellcode habe ich bis jetzt: 

```
@Override
     protected void paintComponent(final Graphics g) {
         super.paintComponent(g);
         Dimension size = getSize();
         g.drawRect(size.width/2-breiteKasten/2, 10, breiteKasten, hoeheKasten);
         
         drawLeft(g, size.height, size.width/2, root.getVater(), 1);
    
     }

	private void drawLeft(Graphics g, int hoehe, int weite, Person vater, int ebene) {
		int x = (weite/2)-(breiteKasten/2);
		int y = hoeheKasten*ebene+25;
		System.out.println("Weite: " + weite + "    Hoehe: " + hoehe + "    Ebene: " + ebene);
		System.out.println("Links oben: " + x + " / " + y);
		 g.drawRect((weite/2)-(breiteKasten/2), hoeheKasten*ebene+25, breiteKasten, hoeheKasten);
		 if(vater.getVater() != null) {
			 drawLeft(g, hoehe, weite/2, vater.getVater(), ebene+1);
		 }
	}
```

Wenn ich mir die Ausgaben meiner System.out.println's ansehe, bekomme ich 2x die gleichen Ergebnisse. Kann es sein, dass ich entweder einen Denkfehler mache oder, dass man bei paintComponent nicht rekursiv arbeiten kann? Oder woran hängt es ... ich steige nicht mehr sonderlich durch ^^ 

Das ganze Iterativ zu lösen erschien mir um weiten schwerer, da ich die ganzen Abbiegungen im Baum dann nicht hinbekommen würde bzw. ich keinen Weg kenne dies hinzubekommen.

Ich hoffe es hat jemand einen Tipp für mich bzw. kann mir erstmal verraten, ob paintComponent überhaupt Rekursiv geht ...

Vielen Dank im Voraus 

Gruß,


----------



## Michael... (29. Nov 2011)

Bei einem Baum ist man bei der Rekursion besser aufgehoben ;-)
Was mich iritiert ist das getVater()? Üblicherweise fängt man ja vom Wurzelknoten an und hangelt sich dann die Kindknoten entlang. Vermute aber es hängt damit zusammen, dass ein Familienstammbaum dargestellt werden soll.
Die Methode würde ich drawNode(...) o.ä. nennen, da es ja (von der Systematik) egal ist ob der Knoten rechts oder links steht

```
drawNode(Node node, ...) {
    zeicheneRepräsentationVon(node);
    drawNode(node.getLeftNode(), ...);
    drawNode(node.getRightNode(), ...);
}
```

Die Rechnerei ist mir zu wirr, um diese jetzt auf Korrektheit zu überprüfen. Per System.out.println(...) könnte man überprüfen ob der Baum korrekt rekursiv durchlaufen wird.

Um da mehr dazu zu sagen, wäre es vielleicht nicht schlecht Deinen Code auf ein kompilibares Minimum zu reduzieren und zu posten.


----------



## watsefaq (29. Nov 2011)

Also 

Da das ganze aus Java EE stammt (also das Problem), bilden unsere Personen gleich Entitäten ab. Daher habe einfach 2 Funktionen geschrieben, welche zu einem übergebenen Knoten Vater und Mutter ausgeben (getVater() und getMutter()). 

Ich hatte mir das so gedacht, dass ich erst den root Knoten (also die Person von der aus gezeichnet werden soll) zeichne und dann einfach rekursiv das immer wieder für den linken und rechten Teilbaum aufrufe. In dem Quellcode natürlich erstmal nur repräsentativ der linke Teilbaum ... der rechte würde dann folgen, wenn mein Problem geklärt ist.

Diese ganzen "Werte" sind Berechnungen, dass das ganze auf mein JPanel passt bzw. halbwegs ordentlich aussieht. 

Die System.out.println's geben leider genau den gleichen Wert zurück. Also die Funktion wird 2x aufgerufen, jedoch verändert sich keiner der Übergabeparameter dabei ... das finde ich etwas suspekt!

Daher die Vermutung -> Geht Rekursion innerhalb von paintComponent nicht?
Oder mache ich in meiner Rekursion etwas falsch?


----------



## Michael... (29. Nov 2011)

watsefaq hat gesagt.:


> Da das ganze aus Java EE stammt (also das Problem), bilden unsere Personen gleich Entitäten ab. Daher habe einfach 2 Funktionen geschrieben, welche zu einem übergebenen Knoten Vater und Mutter ausgeben (getVater() und getMutter()).


Keine Ahnung was das mit EE zu tun hat, aber für es zeichnen sollte es egal sein, ob left/right oder Mutter/Vater


watsefaq hat gesagt.:


> Die System.out.println's geben leider genau den gleichen Wert zurück. Also die Funktion wird 2x aufgerufen, jedoch verändert sich keiner der Übergabeparameter dabei ... das finde ich etwas suspekt!
> 
> Daher die Vermutung -> Geht Rekursion innerhalb von paintComponent nicht?
> Oder mache ich in meiner Rekursion etwas falsch?


Das ist durchaus supsekt, aber es gibt keinen Grund warum Rekursion innerhalb von paintComponent nicht mehr funktionieren sollte:

```
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class TreeDraw {

	public TreeDraw() {
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setBounds(20, 20, 600, 300);
		TreePanel treePanel = new TreePanel();
		frame.add(treePanel);
		frame.setVisible(true);

		Person person = new Person("Ralf", new Person("Alfred"), new Person("Beate"));
		person = new Person("Susi", person, new Person("Claudia"));
		Person horst = new Person("Horst", new Person("A"), new Person("B"));
		person = new Person("Holger", horst, person);
		treePanel.setRootPerson(person);
	}

	class TreePanel extends JPanel {

		private Person root;

		public void setRootPerson(Person person) {
			this.root = person;
			this.repaint();
		}

		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			if (root != null)
				paintPerson(g, root, 0, this.getWidth() / 2);
		}

		int h = 30;

		private void paintPerson(Graphics g, Person person, int level, int x) {
			g.fillOval(x, 10 + level * h, 10, 10);
			g.drawString(person.getName(), x + 15, 20 + level * h);
			if (person.getLeft() != null) {
				g.drawLine(x + 5, 15 + level * h, x - (4 - level) * 20 + 5, 15 + (level + 1) * h);
				paintPerson(g, person.getLeft(), level + 1, x - (4 - level)	* 20);
			}
			if (person.getRight() != null) {
				g.drawLine(x + 5, 15 + level * h, x + (4 - level) * 20 + 5, 15 + (level + 1) * h);
				paintPerson(g, person.getRight(), level + 1, x + (4 - level) * 20);
			}
		}
	}

	class Person {
		private Person father;

		private Person mother;

		private String name;

		public Person(String name) {
			this(name, null, null);
		}

		public Person(String name, Person father, Person mother) {
			this.name = name;
			this.father = father;
			this.mother = mother;
		}

		public String getName() {
			return name;
		}

		public Person getLeft() {
			return father;
		}

		public Person getRight() {
			return mother;
		}
	}

	public static void main(String[] s) {
		new TreeDraw();
	}
}
```


----------



## watsefaq (30. Nov 2011)

Mhh... dann probier ich mal basierend auf deiner Lösung meinen Fehler zu finden 

Was das mit Java EE zutun hat -> Eigentlich nix, aber ich dachte ich erwähne es trotzdem mal ... nicht, dass es nachher doch irgendwie einen Zusammenhang gibt 

Danke nochmal


----------

