# Hilfe bei einer GUI Programmierung mit Graph



## eric1980 (30. Jan 2009)

Hey Leute ich benötige unbedingt Hilfe bei der folgenden Aufgabe und eigentlich bis gestern  Habe vergessen die Aufgabe abzugeben und muss die bis Sonntag wegschicken, sonst war ein halbes Jahr lernen umsonst:
Bitte um Hilfe!!!
Es soll eine GUI programmiert werden, mit MVC:

b) Um von Anfang an eine bessere Strukturierung des Programms zu erzielen, programmieren Sie eine Node-Klasse, die einen Knoten innerhalb einer Graphstruktur darstellen soll. Ein Node-Objekt soll als Eigenschaften eine id (eindeutige Bezeichnung), eine Position (x-, y-Koordinaten), eine Größe und eine Farbe (Color-Objekt) besitzen. Die Node-Klasse soll mindestens zwei Konstruktoren anbieten. Eine, die die Position und die Größe des Knotens als Argument bekommt und eine, die nach Eingabe eines Wertebereichs die Position mit Hilfe eines Random-Objekts zufällig erzeugt.
Die wichtigste Methode in dieser Klasse, weil für die Ereignisbehandlung notwendig ist, ist die inNode-Methode, die nach Eingabe einer Punktposition entscheidet, ob sich der Punkt innerhalb der Knotenfläche befindet oder nicht.
public boolean inNode( int x, int y )
oder
public boolean inNode( Point p )
c) Als Zweites programmieren Sie eine Graph-Klasse.
Diese Klasse soll Graph-Objekte darstellen. Ein Graph-Objekt besteht aus einer Menge von Knoten und einer Menge von Verbindungen zwischen den Knoten (Kanten). Die Verbindungen zwischen den Knoten können mit Hilfe einer Adjazenzmatrix oder einer Adjazenzliste implementiert werden (siehe Vorlesungsfolien). Die Graph-Klasse soll mindestens einen Konstruktor anbieten, der bei Eingabe einer Knotenzahl und eines Wertebereichs für die Position der Knoten des Graphs alle Knoten mit zufälligen Positionen und zufälligen Verbindungen zwischen den Knoten erzeugt.
d) Schreiben Sie von Anfang an eine print-Methode, die die Verbindungen zwischen den Knoten in Textform ausgibt und eine connect-Methode, die neue Verbindungen zwischen zwei eingegebenen Knoten ermöglicht.
e) Schreiben Sie eine paint-Methode, damit das Graph-Objekt sich selbst bei Eingabe eines graphischen Kontexts (Graphics-Objekt) auf beliebige Behälter-Objekte zeichnen kann.
f) Programmieren Sie eine GraphPicture-Klasse als Unterklasse der JPanel-Klasse, die in Ihrem Konstruktor ein Graph-Objekt als Parameter bekommt und dieses Graph-Objekt entsprechend zeigt.
g) Innerhalb der GraphPicture-Klasse sollen die MouseListener- und die MouseMotionListener-Interfaces implementiert werden (siehe Vorlesungsbeispiel), so dass möglichst einfach die Positionen der Knoten innerhalb des Graph-Objekts verändert werden können, und neue Verbindungen zwischen den Knoten mit einfachen Maus-Klicks hergestellt werden können.
h) Zum Schluss programmieren Sie eine Fenster-Klasse, die das Graph-Objekt auf dem Bildschirm sichtbar macht.

Bin für jedes Codestück dankbar!


----------



## André Uhres (30. Jan 2009)

1234567890


----------



## 0x7F800000 (31. Jan 2009)

Das ist jetzt echt ziemlich viel Holz für eine kleine Frage in einem Forum... Soll sich hier jetzt einer Hinhocken und dir in 10 Minuten so ein ~1000-Zeilen Projektchen eintippen? Das ist jetzt echt ein wenig kurzfristig :shock:


----------



## diggaa1984 (31. Jan 2009)

sozialisiere dich, spendiere 1-2 bier und schreib das was du eventuell erschnorrst n bissel um 

bei uns sind die aufgaben meist gestaffelt und werden durchgehend abgenommen .. wenn's nur eine aufgabe gibt, die am ende fertig sein soll, dann tja, hast dich irgendwie falsch organisiert .. gerade wenn man weiss das man damit vielleicht probleme hat ... würde zumindest mich, das ganze nich in ruhe lassen .. sodass ich mich schon früher drum kümmern würde wie ich das packe etc.


----------



## eric1980 (31. Jan 2009)

hier meine ersten ausführungen zu b).
ich brauche dabei hilfe bei der methode inNode und bei dem zweiten Konstruktor (random)


import java.awt.Color;


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Eric
 */
public class Node {

    int id;
    int x, y;
    int size;
    Color color = Color.BLUE;

    public Node(int x, int y, int size){
        this.x=x;
        this.y=y;
        this.size = size;
    }
    public Node(){

    }


    public boolean inNode(int x, int y){

    }
}


```

```


----------



## eric1980 (31. Jan 2009)

so hab hier noch mal was für die graph klasse geschrieben, aber da habe ich echt keine ahnung, ob das irgendwie stimmt. ich habe es einfach nach meinem besten wissen gemacht.

import java.awt.Color;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Vector;



public class Graph{

ArrayList<Node> adjList = new ArrayList<Node>();
ArrayList<Edge> edges = new ArrayList<Edge>();
int nextId = 0;
// für BFS
Vector<Node> queue = new Vector<Node>();

Node startNode;

public void initBFS(){
for( Node node : adjList ){
node.color = Color.WHITE;
node.dist = Integer.MAX_VALUE;
node.pred = null;
}
this.startNode = adjList.get(0);
for ( Edge edge : edges ){
edge.setMarked(false);
}
}
public void BFS(){
Node v_node, d_node = null;
this.startNode.setColor(Color.GRAY);
this.startNode.dist = 0;
this.queue.add( startNode );
while( !queue.isEmpty() ){
v_node = queue.firstElement();
Iterator iter = v_node.neighbours.iterator();
while ( iter.hasNext() ){
d_node = (Node) iter.next();
if ( d_node.color == Color.WHITE ){
d_node.setColor(Color.GRAY);
d_node.dist = v_node.dist+1;
d_node.pred = v_node;
queue.add(d_node);
}
}
queue.remove(0);
v_node.setColor(Color.BLACK);
}


----------



## diggaa1984 (31. Jan 2009)

> ich brauche dabei hilfe bei der methode inNode


hm als idee ... Du hast ja eine Größe und eine Position die dem Node zugeordnet werden, simplerweise kannst damit ne Kreisfläche erstellen, das heisst du kannst auch wenn du einen Punkt, oder 2  Koordinaten in der inNode-Methode bekommst guggn ob der Abstand vom Mittelpunkt des Nodes (quasi this.x und this.y) zum gegebenen Parameter der inNode-Methode die Größe überschreitet oder nicht ... die Größe würde also in dem Fall deinem Radius entsprechen.

Denke als Ansatz sollte das reichen, das ist ja simpelste Mathematik.

was den Konstruktor angeht schau mal hier rein: java.util.Random


> [...] nach Eingabe eines Wertebereichs [...]


da hast also ne obere und ne untere Grenze (jeweils für x und y) und innerhalb dieser Grenzen soll Random eine Zahl generieren


```
import java.util.Random;

public void foo(int lowerX, int higherX) {
    int randomX;

    Random r = new Random();

    // Wert von 0 - exklusive(!!) Klammerausdruck (daher +1 als Korrektur bei int-Werten)
    int tempVal = r.nextInt(higherX-lowerX+1); 

    randomX = tempVal + lowerX; //generierten Wert auf untere Grenze addieren et voilà
}
```

und korrigier mal bitte die code-tags ^^


----------



## eric1980 (31. Jan 2009)

eine frage an dch...also erst mal vielen dank für die erste antwort!
also so ein node, ist ja ein knoten, kann ich den mit einem einfach punkt vergleichen, der eine größe und position 
erhält?
die inNode Methode, was soll die machen? gucken ob der node innerhalb von was liegt?
die random methode die du geschrieben hast, kann ich ja so nicht verwenden, ich sollte das ja in einem konstruktor
machen und einen wertebereich angeben?
und soweit ich das richtig verstanden habe, soll die random methode danach die position des node erzeugen, also this.x und this.y?


----------



## diggaa1984 (31. Jan 2009)

eric1980 hat gesagt.:
			
		

> also so ein node, ist ja ein knoten, kann ich den mit einem einfach punkt vergleichen, der eine größe und position erhält?





			
				Aufgabenstellung hat gesagt.:
			
		

> Ein Node-Objekt soll als Eigenschaften eine id (eindeutige Bezeichnung), eine Position (x-, y-Koordinaten), eine Größe und eine Farbe (Color-Objekt) besitzen


 .. also ob du aus ner Koordinate und ner Größe nen Kreis, nen Trapez oder hyperbolischen Würfel machst is dir vermutlich überlassen ^^ .. Kreis macht sich in anbetracht der inNode-Problematik ganz gut 



> die inNode Methode, was soll die machen? gucken ob der node innerhalb von was liegt?


die inNode soll dazu dienen zu prüfen ob ein übergebener Punkt (oder die x/y-Koordinaten) innerhalb des Node-Gebildes liegen, was durch dessen Koordinaten und der Größe beschrieben wird, vermutlich brauchst du das, da du später die Nodes mit der Maus verschieben können sollst, da würdest du also die Mauskoordinaten übergeben, und wenn die im Knoten liegen, kannst durch klicken und ziehen selbigen bewegen. Liegst du ausserhalb passiert nix



> die random methode die du geschrieben hast, kann ich ja so nicht verwenden, ich sollte das ja in einem konstruktor
> machen und einen wertebereich angeben?
> und soweit ich das richtig verstanden habe, soll die random methode danach die position des node erzeugen, also this.x und this.y?



richtig, das sollte dir nur als Hinweis dienen wie du damit arbeiten kannst. Den Konstruktor musst noch selbst baun, aber wie du dazu Random nutzen könntest, wird aus meine Methode voll und ganz ersichtlich


----------



## eric1980 (31. Jan 2009)

okay...das habe ich soweit verstanden:
aber für den konstruktor:

public Node() muss ich ja einen wertebereich angeben. wie mache ich das denn? also der wertebereiche sollte sich ja auf die position beziehen, d.h. der wertebereich sollte angeben, in welchem bereich sich die x und y koordinaten
(werte) bewegen.
Leider keine Ahnung wie ich das mache :-(


----------



## diggaa1984 (31. Jan 2009)

also ich würde den Wertebereich ja auch als Parameter in Empfang nehmen .. "nach Eingabe eines Wertebereiches" is meiner Meinung nach ungünstig ausgedrückt. Später hast ja eh eine grafische Oberfläche, ich denke das es dann Sinn macht wenn der Nutzer per Dialog dann einen Wertebereich angeben kann, dessen (Dialog-)Inhalte dann an den Konstruktor geleitet werden

also:


```
public Node(int lowerX, int lowerY, int higherX, int higherY) {
 //mein Randomkram darauf angewendet
}
```

wäre jetzt mal die intuitivste Lösung ^^
praktisch wäre hier auch, eine Standardgröße in der Klasse festzulegen


```
private static final int DEFAULTSIZE = 2;

public Node(int x, int y, int size) {
 ...
}

public Node(int lowerX ... etc) {
 <randomkram (liefert randomX und randomY>
 this(randomX,randomY,DEFAULTSIZE);
}

//damit leitest deine Berechnungen an den andern Konstruktor weiter, welcher dir wie gewohnt die
//Parameter in die Klassenvariablen schreibt
```

ich sehe auch eben, das du die inNode-Methode später auch dazu verwenden musst, um zu sehen ob sich 2 zufällig erzeugte Nodes überschneiden oder nicht (der Abstand der Mittelpunkte sollte größer sein als die Summe beider Radien .. dann siehst im Falle von ganzzahligen Koordinaten noch die Verbindungslinie, bei Abstand == Summe der Radien, würdest die Verbindung vermutlich net mehr sehen).

Nur mal so, mit der Graph-Klasse hab ich mich nun noch nicht näher beschäftigt


----------



## eric1980 (31. Jan 2009)

```
import java.awt.Color;
import java.util.Random;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Eric
 */
public class Node {

    int id;
    int x, y;
    int size;
    Color color = Color.BLUE;
    int higherX;
    int higherY;
    int lowerX;
    int lowerY;
    
    public Node(int x, int y, int size){
        this.x=x;
        this.y=y;
        this.size = size;
    }
   
	

	public Node(int higherX, int higherY, int lowerX, int lowerY) {
		this.higherX = 50;
        this.higherY = 50;
        this.lowerX  = 0;
        this.lowerY  = 0;
        int randomX; 
        int randomY;

    Random r = new Random(); 

    // Wert von 0 - exklusive(!!) Klammerausdruck (daher +1 als Korrektur bei int-Werten) 
    int tempVal = r.nextInt(higherX-lowerX+1);
    int tempVal1 = r.nextInt(higherY-lowerY+1);

    randomX = tempVal + lowerX; //generierten Wert auf untere Grenze addieren et voilà 
    randomY = tempVal1 + lowerY;
}
 
   
}
```

was hältst du davon???

[/code]


----------



## diggaa1984 (31. Jan 2009)

```
int higherX; 
    int higherY; 
    int lowerX; 
    int lowerY;
```

das brauchst in der Klasse selbst ja nicht, das sind nur parameter des einen Konstruktors mit denen du x und y werte bestimmen sollst. Aehm ich weiss nicht wann du mein Bsp gesehen hast, hab oft editiert, aber schau dir mal meine Konstruktor-Tipps an. Die Berechnung an sich machst ja richtig, und diese berechneten Werte kannst dann in den anderen Konstruktor schieben, welcher x y und size bekommt.

Was du noch nicht machst ist das randomX und randomY zu speichern, das fehlt noch.
die Angaben von higher und lower-stuff im 2. Konstruktor (= 50 etc.) dienen hoffentlich nur zum Test  .. weil die brauchst du ja nich setzen, die bekommst ja übergeben


----------



## eric1980 (31. Jan 2009)

```
public Node(int higherX, int higherY, int lowerX, int lowerY) {
		this.higherX =higherX;
        this.higherY = higherY;
        this.lowerX  = lowerX;
        this.lowerY  = lowerY;
        int randomX; 
        int randomY;

    Random r = new Random(); 

    // Wert von 0 - exklusive(!!) Klammerausdruck (daher +1 als Korrektur bei int-Werten) 
    int tempVal = r.nextInt(higherX-lowerX+1);
    int tempVal1 = r.nextInt(higherY-lowerY+1);

    randomX = tempVal + lowerX; //generierten Wert auf untere Grenze addieren et voilà 
    randomY = tempVal1 + lowerY;
}
```

wie meinst du das, : das brauchst in der Klasse selbst ja nicht, das sind nur parameter des einen Konstruktors mit denen du x und y werte bestimmen sollst.

wenn ich die nicht in der klasse angebe, sagt er mir doch, create field!
wie soll ich denn random x und y speichern?[/code]


----------



## diggaa1984 (31. Jan 2009)

```
public Node(int lowerX ... etc) { 
//this.higherX ... kann alles weg, du arbeitest doch mit den parametern und nich 
//mit Werten der klasse um x und y zu bestimmen .. dann fällt auch dein
//creatField problem weg

<//der ganze randomkram> 

//Aufruf des anderen Konstruktors mit errechneten Werten und der
//in der klasse definierten Standardgroesse
this(randomX,randomY,DEFAULTSIZE); 
}
```


----------



## eric1980 (31. Jan 2009)

wie rufe ich denn jetzt da den anderen konstruktor auf, also den mit x, y, und size und übergebe da die random 
werte??



```
private static final int DEFAULTSIZE = 2;
    
    public Node(int x, int y, int size){
        this.x=x;
        this.y=y;
        this.size = size;
    }
   
	

	public Node(int higherX, int higherY, int lowerX, int lowerY) {
		
        int randomX; 
        int randomY;

    Random r = new Random(); 

    // Wert von 0 - exklusive(!!) Klammerausdruck (daher +1 als Korrektur bei int-Werten) 
    int tempVal = r.nextInt(higherX-lowerX+1);
    int tempVal1 = r.nextInt(higherY-lowerY+1);

    randomX = tempVal + lowerX; //generierten Wert auf untere Grenze addieren et voilà 
    randomY = tempVal1 + lowerY;
    
    this(randomX,randomY,DEFAULTSIZE);
}
```


----------



## diggaa1984 (31. Jan 2009)

naja genau so ^^


----------



## eric1980 (31. Jan 2009)

aber der sagt mir: call to this must be first statement in constructor und gibt mir einen fehler


----------



## diggaa1984 (31. Jan 2009)

Tatsache, habsch grad nich dran gedacht, ja dann machst eben das selbe wie oben nochmal (also zuweisung der Klassenvariablen)[/code]


----------



## eric1980 (31. Jan 2009)

so??
randomX = tempVal + lowerX; //generierten Wert auf untere Grenze addieren et voilà 
    randomY = tempVal1 + lowerY;

    this.x = randomX;
    this.y = randomY;
    this(randomX,randomY,DEFAULTSIZE);
}

nur wenn ich das so machen bekomme ich noch immer die fehlermdeldung


----------



## diggaa1984 (31. Jan 2009)

ne dann auch

this.size = DEFAULTSIZE;


----------



## eric1980 (31. Jan 2009)

noch immer!


----------



## diggaa1984 (31. Jan 2009)

```
this(randomX,randomY,DEFAULTSIZE);
```

das brauchst ja dann nicht mehr, das kannst also rausnehmen


----------



## eric1980 (31. Jan 2009)

```
import java.awt.Color;
import java.util.Random;


public class Node {

    int id;
    int x, y;
    int size;
    Color color = Color.BLUE;
    private static final int DEFAULTSIZE = 2;
    
    
	

	public Node(int higherX, int higherY, int lowerX, int lowerY) {
		
        int randomX; 
        int randomY;

    Random r = new Random(); 

    // Wert von 0 - exklusive(!!) Klammerausdruck (daher +1 als Korrektur bei int-Werten) 
    int tempVal = r.nextInt(higherX-lowerX+1);
    int tempVal1 = r.nextInt(higherY-lowerY+1);

    randomX = tempVal + lowerX; //generierten Wert auf untere Grenze addieren et voilà 
    randomY = tempVal1 + lowerY;
    
    this.x = randomX;
    this.y = randomY;
    this.size= DEFAULTSIZE;
    
}
    
also die node klasse ist somit fertig, oder hast du noch verbesserungsvorschläge?
```


----------



## diggaa1984 (31. Jan 2009)

der andere Konstruktor und das inNode!?

eventuell kommen noch andere Methoden dazu, weiss ich grad nicht, aber das war zumindest der teil aus a)


----------



## eric1980 (31. Jan 2009)

```
import java.awt.Color;
import java.util.Random;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Eric
 */
public class Node {

    int id;
    int x, y;
    int size;
    Color color = Color.BLUE;
    private static final int DEFAULTSIZE = 2;
    
    public Node(int x, int y, int size){
        this.x=x;
        this.y=y;
        this.size = size;
    }
   
	

	public Node(int higherX, int higherY, int lowerX, int lowerY) {
		
        int randomX; 
        int randomY;

    Random r = new Random(); 

    // Wert von 0 - exklusive(!!) Klammerausdruck (daher +1 als Korrektur bei int-Werten) 
    int tempVal = r.nextInt(higherX-lowerX+1);
    int tempVal1 = r.nextInt(higherY-lowerY+1);

    randomX = tempVal + lowerX; //generierten Wert auf untere Grenze addieren et voilà 
    randomY = tempVal1 + lowerY;
    
    this.x = randomX;
    this.y = randomY;
    this.size= DEFAULTSIZE;
    }
    
    public boolean inNode(int x, int y){
        
            return true;
        }
    
    
}
	

	
    
   
wie vergleiche ich denn in der inNode Methode die Werte x, y mit den x,y werten von Node? muss ich dabei dir random werte verwenden? wenn ja, müsste ich sie doch als klassenvariablen deklarieren?
```


----------



## diggaa1984 (31. Jan 2009)

wenn du mit dem Konstruktor einen Node angelegt hat, dann speicherst du die werte für die Koordinaten doch in den Klassenvariabeln x und y ab. Das heisst ein Knoten weiss immer wo er liegt. Wenn nun in inNode die Koordinaten übergeben werden, für die geprüft werden soll, ob sie innerhalb des Nodes liegen oder nicht, dann musst du eben testen ob diese Koordinaten in der aufgespannten fläche liegen oder nicht. mit nem Kreis geht das eben ganz einfach.

Da prüfst den abstand der übergebenen Punkte zu den Koordinaten des Mittelpunktes des Nodes (bestehen aus x und y aus den Klassenvariablen). Das random hat damit nix mehr zu tun.

Wie gesagt, stumpfes vergleichen der Werte würde dir nur sagen, ob die übergebenen Koordianten genau den Koordinaten des Nodes entsprechen. Aufgrund der Tatsache das du eine Größe gegegeben hast, bildet sich damit rein logisch ne Fläche die der Node umfasst. Und du musst nun schauen ob die übergebenen Koordinaten in der Fläche liegen und nicht nur ob sie den x/y-Werten des Nodes entsprechen.

ausserdem noch kleine schönheitskorrektur (damits einheitlich wird):

```
private int id; 
private int x, y; 
private int size; 
private Color color; //je nachdem wenn du das brauchst .. bisher nicht notwendig

private static final Color DEFAULTCOLOR = Color.BLUE; 
private static final int DEFAULTSIZE = 2;
```

ist dir bewusst was "private", "static" und "final" für ne Wirkung haben?
nicht das dich das einer fragt, und du weisst nich was das soll


----------



## eric1980 (31. Jan 2009)

um ehrlich zu sein habe ich keine ahnung wie das funktionieren soll, mit der methode inNode und dem kreis.


was heisst: Da prüfst den abstand der übergebenen Punkte zu den Koordinaten des Mittelpunktes des Nodes

also ich habe ja jetzt einen node angelegt. und habe für diesen x und y werte, aber mit was muss ich die denn vergleichen. wird in der inNode Methode auch noch was angelegt???
innerhalb welchen Kreises???


----------



## diggaa1984 (31. Jan 2009)

na dein inNode hat doch ne Größe als Klassenvariable .. die wird sich der Herr Aufgabensteller nicht aus Spaß da reingedacht haben ^^ .. Sprich x,y und size bilden eine Fläche, hier gehen wir nun einfach mal vonnem Kreis aus (size ist dann also unser radius), weil sich das ganz toll rechnet ^^.

Nen Knoten in einer Grafik is ja auch nicht nur ein Pixel, weil dann würdest den vermutlich nich als solchen erkennen, das is der Hintergrund meiner Schlussfolgerungen.

So also hat unser Node ne Kreisfläche, legen wir einfach fest.

Nun musst du innerhalb von inNode prüfen, ob sich der übergebene Parameter innerhalb dieser Fläche befindet oder nicht, um das zu entscheiden, musst du nur berechnen wie weit diese 2 Punkte auseinander liegen (der übergebene und der durch x/y gebildete Knoten in Node) ... ist der Abstand <= size .. dann würde sich der übergebene Punkt innerhalb der Kreisfläche befinden, und somit im Knoten liegen.

Ist der Abstand > size liegt der Punkt ausserhalb.




```
import java.util.Math;

public boolean inNode(int x, int y) {
   double distance = Math.sqrt(Math.pow((this.x - x),2)+Math.pow((this.y - y),2));

   if (distance > this.size)
        return false;

   return true;
}
```

ohne Test grad hingehackt


----------



## eric1980 (31. Jan 2009)

scheint zu funktionieren 
super den ersten teil habe ich (durch dich), vielen dank!

hast du schon mal geschaut, wie ich weitermachen muss. irgend eine idee??


----------



## diggaa1984 (31. Jan 2009)

naja c und d sollten eigentlich gehen, wie adjazenzmatrizen/-listen aufgebaut sein müssen scheint ja im script zu stehen, und wie man konstruktoren anlegt weisst ja nun auch .. ich kann leider nicht weiter helfen .. abendplanung

dennoch viel erfolg


----------

