# ein Rechteck zeichnen



## Leeloo (24. Feb 2004)

Hallo Leute,

bin das erste Mal hier und hoffe, ihr könnt mir weiterhelfen. Habe schon in den vielen Forenbeiträgen nach einer Lösung gesucht, nur leider keine passende gefunden, denke ich.   

Also, ich habe mir in Swing ein Oberfläche mit Menupunkten und einer weißen Zeichenfläche erstellt (das war wirklich nicht schwer). Nun möchte ich per Klick auf "Neues Rechteck" im Menu, dass 1. ein Fenster aufgeht und ich dort einige Dinge festlegen kann, wie z.B. den Namen des Rechtecks und 2. dass das Rechteck + Name dann auf der Zeichenfläche erscheint. Die Sache ist nur die, ich hab einfach keine Ahnung, wie ich das machen soll.  :?: 
Ich weiß schon, dass hier zuerst


```
if (event.getActionCommand().equals("Neues Rechteck"))
    {
    	//...
    }
```

und dann hier


```
public void paintComponent(Graphics g)
    { 
        super.paintComponent(g);
        Graphics2D g2 =(Graphics2D)g;
        //...    
     }
```

noch was hin muss. Bloß was und wie, damit ich ein Rechteck zeichnen kann.
Dass ich mit 

```
g2.drawRect(x,y,sizex,sizey);
```
ein Rechteck zeichnen kann weiß ich. Es soll halt per Klick auf "Neues Rechteck" im Menu erscheinen.

Später soll es dann noch möglich sein, das Rechteck beliebig mit der Maus zu verschieben und anzuklicken.
Aber erstmal alles schrittweise nacheinander. Und vielleicht geht mir auch schon miteinem kleinen Hinweis ein Kronleuchter auf.

Vielen Dank schonmal.
Gruß,
Leeloo


----------



## Beni (24. Feb 2004)

Schreib dir eine Klasse "Rechteck", könnte etwa so aussehen:
	
	
	
	





```
public Rechteck{
  private int x, y, width, height;
  private Color color;
  private boolean fill;

  public Rechteck( int x, ... ){
    this.x = x;
    ...
  }
  
  public void paint( Graphics g ){
    g.setColor( color );

    if( fill )
      g.fillRect( x, y, width, height );
    else
      g.drawRect( x, y, width, height );
  }
}
```

Und in deinem Progi hast du einen Array oder Vector, in dem Du alle Rechtecke gespeichert hast.
Tja, dann noch kurz bei diesen Rechtecken "paint" aufrufen, und da sind sie.


```
public void paintComponent(Graphics g){
  // rects ist ein java.util.Vector, gefüllt mit Instancen von Rechteck
  for( int i = 0; i < rects.size(); i++ )
    ((Rechteck)rects.get(i)).paint( g );
}
```

mfg Beni

P.S. Der Weg zur beliebigen Figur ist hier nicht mehr weit, eine abstrake Basisklasse Drawable könnte so aussehen:

```
public abstract class Drawable{
  private int x, y;
  public abstract void paint( Graphics g ); // wird später die Figur zeichnen
  public void move( int deltaX, int deltaY ){ // Figur mit der Maus verschieben, delta zeigt die Bewegung der Maus
    x += deltaX;
    y += deltaY;
  }
  ...
}
```

und das Rechteck so:
	
	
	
	





```
public class Rechteck extends Drawable{
  private int width, height;
  private Color color;
  private boolean fill;
  ...
}
```


----------



## Leeloo (25. Feb 2004)

Danke für deine Antwort Beni, aber ich schnall es nicht. *aufgeb* Ich bin einfach zu dämlich für sowas


----------



## Beni (25. Feb 2004)

Nee, zu wenig Übung hast Du!

Also: (vielleicht schreibe ich auch zu kompliziert :? )

*Anforderungen sind:*
1. Du musst alle deine Rechtecke irgendwie abspeichern
2. Die Rechtecke sollen so gespeichert werden, dass sie später wieder veränderbar sind

*Meine Antwort darauf:*
a) Fasse ein Rechteck als eine Einheit, ein Objekt, eine Klasse auf. Jede Klasse Rechteck speichert die wichtigen Informationen in sich selbst.
b) Die Rechtecke sollen "sich selbst" zeichnen. Das geschieht mit der Methode _Rechteck.paint( Graphics g )_. Damit sind die Rechtecke unabhängig, und der Code wird übersichtlicher. (Das Zeichnen eines Rechteckes ist einfacher als das Zeichnen vieler Rechtecke)
c) Der Rest deines Programmes hat nun nur noch die Aufgabe eine Liste aller Rechtecke zu speichern (z.B. mit einem _Vector_, oder einem _Array_), und die Methode _paint _der Rechtecke aufzurufen.
d) Später wird der Rest des Programmes noch die Position und Grösse der Rechtecke beeinflussen können.
e) Alles läuft auf eine Trennung zwischen "Das ist Rechteck", und "Das beeinflusst Rechteck" aus.

*Später:*
- Wenn Du genug Übung hast, wirst Du in der Lage sein. Die Klasse Rechteck so umzuschreiben, dass ohne grossen Aufwand Kreise und Dreiecke gezeichnet werden können.


Klarer? Beispielprogram nötig?

Beni


----------



## Beni (25. Feb 2004)

Hier kleines Beispiel, vielleicht hillfts


```
import java.awt.*;
import javax.swing.*;
import java.util.Vector;

public class ExamplePaint extends JFrame {
  public static void main( String[] args ){
    new ExamplePaint();
  }

  private Vector image = new Vector();

  public ExamplePaint(){

// Ein paar Beispiele zusammenbauen
    for( int i = 0; i < 25; i++ ){
      int x1 = (int)(Math.random() * 500);
      int x2 = (int)(Math.random() * 500);
      int y1 = (int)(Math.random() * 500);
      int y2 = (int)(Math.random() * 500);

      Color color = new Color( (int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255) );

      boolean fill = Math.random() > 0.5;

      if( Math.random() > 0.5 )
        image.add( new Rechteck( Math.min(x1, x2), Math.min( y1, y2), Math.abs( x1-x2 ), Math.abs( y1-y2 ), color, fill ));
      else
        image.add( new Oval( Math.min(x1, x2), Math.min( y1, y2), Math.abs( x1-x2 ), Math.abs( y1-y2 ), color, fill ));
    }

    setBounds( 30, 30, 500, 500 );
    setDefaultCloseOperation( EXIT_ON_CLOSE );
    setVisible( true );
  }

// alles zeichnen
  public void paint( Graphics g ){
    for( int i = 0, n = image.size(); i<n; i++ )
      ((Paintable)image.get(i)).paint( g );
  }

}

// Oberklasse, für gemeinsahme Grundlage
abstract class Paintable{
  private int x, y, w, h;
  private Color color;
  private boolean fill;

  public Paintable( int x, int y, int w, int h, Color color, boolean fill ){
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.color = color;
    this.fill = fill;
  }

  public abstract void paint( Graphics g );

  public int getX(){  return x;  }
  public int getY(){  return y;  }
  public int getWidth(){  return w;  }
  public int getHeight(){  return h;  }
  public Color getColor(){ return color; }
  public boolean isFill(){ return fill; }

}

// Rechteck
class Rechteck extends Paintable{
  public Rechteck( int x, int y, int w, int h, Color color, boolean fill){
    super( x, y, w, h, color, fill );
  }
  public void paint( Graphics g ){
    g.setColor( getColor() );
    if( isFill() )
      g.fillRect( getX(), getY(), getWidth(), getHeight() );
    else
      g.drawRect( getX(), getY(), getWidth(), getHeight() );
  }
}


// Oval
class Oval extends Paintable{
  public Oval( int x, int y, int w, int h, Color color, boolean fill){
    super( x, y, w, h, color, fill );
  }
  public void paint( Graphics g ){
    g.setColor( getColor() );
    if( isFill() )
      g.fillOval( getX(), getY(), getWidth(), getHeight() );
    else
      g.drawOval( getX(), getY(), getWidth(), getHeight() );
  }
}
```


----------



## Leeloo (25. Feb 2004)

Ich will ja keine Kreise und Dreiecke zeichnen, bloß nen Rechteck, was später noch per Maus verschoben werden kann, aber das poste ich sicher dann in einem anderen Thread.

hier soll die Funktion aufgerufen werden:

```
if (event.getActionCommand().equals("Neues Rechteck"))
    {
    // Tja, bloß welche?
    }
```

Tja, und wo wird das Rechteck nun gezeichnet?

In meiner Zeichenfläche


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

public class Zeichenflaeche extends JPanel 
{
    private Vector Rechteck;
     
   
    /**
     * Konstruktor mit der Hintergrundfarbe setzen
     */

    public Zeichenflaeche()
    {
      setBackground(Color.white);    
    }

/**
 *
 */
    public void paintComponent(Graphics g)
    {   
        // Hier zeichnen??   Was soll hier hin?        	
    }
  
}
```

Oder in meiner Klasse Rechteck?


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

public class Rechteck
{
	private Zeichenflaeche zf;
	private int x, y, sizex, sizey; 
  	private Color Farbe; 
  	private boolean fuellen; 

	
	public void Rechteck(Zeichenflaeche z)
	{
		zf=z;
		Farbe= new Color(99,00,33);
		fuellen = true;
	}
	
	public void paint(Graphics g)
                { 
	    // Oder hier zeichnen? Was soll hier hin?
                 }  	
}
```


----------



## Beni (25. Feb 2004)

Ich versuchs mal mit etwas Pseudo-Code (und bemerke, dass ich dich immer mehr verwirre. Also: alles ist einfach, sieht nur kompliziert aus!)


Nach dem drücken des Buttons geht's etwa so weiter
	
	
	
	





```
if (event.getActionCommand().equals("Neues Rechteck")){
        Rechteck x = new Rechteck( ... ) // wie auch immer ein neues Rechteck hergestellt wird.
        save( x ); // save speichert das Rechteck an irgendeiner Stelle, wo man es später wiederfindet
        zf.repaint();  // zf ist die Zeichenfläche. Da es jetzt ein neues Rechteck gibt, muss sie neu gezeichnet werden (Das Bild hat sich ja verändert)
    }
```


In der Zeichenfläche gilt:

```
public void paintComponent(Graphics g){   
        /* durch den Aufbau von Swing wird diese Methode automatisch aufgerufen, wenn die Zeichenfläche neu gezeichnet werden soll.
Dies kann durch den Aufruf von repaint(), oder ein Befehl direkt vom Betriebssystem ausgelöst werden.

Sind wir erstmals hier, müssen die Rechtecke (welche irgendwo, irgendwie gespeichert sind) gezeichnet werden.


Wir könnten einfach die Werte aus dem Rechteck auslesen, und zeichnen lassen. Aber ist das nicht eigentlich die Arbeit eines Rechteckes? Liest der Bibliothekar das Buch für uns? Schaut der Verkäufer die DVD welche wir bezahlt haben?

Gedankenexperiment: Wenn man das Panel durch ein Papier (A4, keine Häusschen, gebleicht), und das Rechteck durch einen Bleistift (gut gespitzt) ersetzt, wird mein Argument verständlicher:

Das Papier (=Panel) bietet den Untergrund, aber es zeichnet den Strich nicht. 
Der Bleistift (=Rechteck) zeichnet den Strich auf das Papier (von ihm kommt die Farbe). 

Daher ist es einfacher, wenn wir im Rechteck eine weitere paint-Methode definieren, welche von hier aus aufgerufen wird */

    // mit der Zeit erreichen wir jedes Rechteck, welches früher mit "save" gespeichert wurde.
    while( daSindNochRechtecke() )   // while-Schlaufe
        getNächstesRechteck().paint( g );    // Den Aufruf weiterreichen. Dies hier ist die "Verteilstation", während jedes Rechteck einmal zeichnen darf

    }
```

Im Rechteck geht es nun weiter:
	
	
	
	





```
public void paint( Graphics g ){
    /* Woher diese Graphics  kommt, muss uns nicht weiter interessieren.

Zum Vergleich mit dem Bleistift: Ob man auf einem Papier oder auf einem Tischtuch zeichnet interessiert den Bleistift nicht so sehr. Er gibt einfach eine gewisse Menge Graphitstaub ab, welcher als Linie sichtbar wird */

    // Zeichnen unter Berücksichtigung aller Parameter die in diesem Rechteck gespeichert sind.
    g.setColor( ... );    
    g.drawRect( ... ); 
}
```


----------

