commit e0dc0987df24548b267f3d29db553c67960b6827 Author: Alparslan Bayramli Date: Mon Oct 16 15:13:24 2023 +0200 Initial sharing of project diff --git a/Aufbau.java b/Aufbau.java new file mode 100644 index 0000000..9611366 --- /dev/null +++ b/Aufbau.java @@ -0,0 +1,22 @@ + +/** + * Baut im Konstruktor das Szenarium auf + * + * @author Albert Wiedemann + * @version 1.0 + */ +class Aufbau +{ + + /** + * Legt die benötigten Objekte an. + */ + Aufbau () + { + new KreisBesser(150, 150, 50, "rot"); + new DreieckBesser(200, 50, 60, 50, "grün"); + new RechteckBesser(100, 220, 200, 50, "grün"); + new RechteckBesser(270, 60, 130, 70, "blau"); + new DreieckBesser(350, 190, 70, 80, "rot"); + } +} diff --git a/Aufbau2.java b/Aufbau2.java new file mode 100644 index 0000000..82c282b --- /dev/null +++ b/Aufbau2.java @@ -0,0 +1,26 @@ + +import java.util.*; +/** + * Baut im Konstruktor das Szenarium auf + * + * @author Albert Wiedemann + * @version 1.0 + */ +class Aufbau2 +{ + /** der Zufallsgenerator */ + Random zufall; + + /** + * Legt die benötigten Objekte an. + */ + Aufbau2 () + { + zufall = new Random(); + new RechteckBesser(zufall.nextInt(400), zufall.nextInt(200), 200, 50, "grün"); + new RechteckBesser(zufall.nextInt(400), zufall.nextInt(200), 130, 70, "blau"); + new DreieckBesser(zufall.nextInt(400) + 50, zufall.nextInt(200), 60, 50, "grün"); + new DreieckBesser(zufall.nextInt(400) + 50, zufall.nextInt(200), 70, 80, "rot"); + new KreisBesser(zufall.nextInt(400) + 50, zufall.nextInt(150) + 50, 50, "rot"); + } +} diff --git a/Dreieck.java b/Dreieck.java new file mode 100644 index 0000000..db1914f --- /dev/null +++ b/Dreieck.java @@ -0,0 +1,171 @@ + +/** + * Wrapperklasse für ein Dreieck auf der Zeichenfläche. + * + * @author Albert Wiedemann + * @version 1.0 + */ +public class Dreieck +{ + /** x-Position der Spitze. */ + private int x; + /** y-Position der Spitze. */ + private int y; + /** Breite des umgebenden Rechtecks. */ + private int breite; + /** Höhe des umgebenden Rechtecks. */ + private int höhe; + /** Farbe des Dreiecks. */ + private String farbe; + /** Sichtbarkeit des Dreiecks. */ + private boolean sichtbar; + /** Drehwinkel (mathematisch positiver Drehsinn) des Dreiecks in Grad. */ + private int winkel; + /** Referenz auf das Delegate-Objekt. */ + Zeichenfenster.GrafikSymbol symbol; + + /** + * Der Konstruktor erzeugt das Delegate-Objekt + */ + Dreieck () + { + x = 60; + y = 10; + breite = 100; + höhe = 100; + farbe = "rot"; + sichtbar = true; + winkel = 0; + symbol = Zeichenfenster.SymbolErzeugen(Zeichenfenster.SymbolArt.dreieck); + symbol.PositionSetzen(x - breite / 2, y); + symbol.GrößeSetzen(breite, höhe); + symbol.FarbeSetzen(farbe); + symbol.SichtbarkeitSetzen(sichtbar); + symbol.WinkelSetzen(winkel); + } + + /** + * Setzt die Position (der Spitze) des Dreiecks. + * @param x x-Position der Spitze + * @param y y-Position der Spitze + */ + void PositionSetzen(int x, int y) + { + this.x = x; + this.y = y; + symbol.PositionSetzen(x - breite / 2, y); + } + + /** + * Verschiebt das Dreieck um die angegebenen Werte. + * @param deltaX Verschiebung in x-Richtung + * @param deltaY Verschiebung in y-Richtung + */ + void Verschieben(int deltaX, int deltaY) + { + x += deltaX; + y += deltaY; + symbol.PositionSetzen(x - breite / 2, y); + } + + /** + * Dreht das Dreieck + * @param grad Drehwinkel (mathematisch positiver Drehsinn) im Gradmass + */ + void Drehen(int grad) + { + winkel += grad; + symbol.WinkelSetzen(winkel); + } + + /** + * Setzt die Größe des Dreiecks. + * @param breite (neue) Breite + * @param höhe (neue) Höhe + */ + void GrößeSetzen (int breite, int höhe) + { + this.breite = breite; + this.höhe = höhe; + symbol.GrößeSetzen(breite, höhe); + symbol.PositionSetzen(x - breite / 2, y); + } + + /** + * Setzt die Farbe des Dreiecks. + * Erlaubte Farben sind: + * "weiß", "weiss", "rot", "grün", "gruen", "blau", "gelb", + * "magenta", "cyan", "hellgelb", "hellgrün", "hellgruen", + * "orange", "braun", "grau", "schwarz" + * Alle anderen Eingaben werden auf die Farbe schwarz abgebildet. + * @param farbe (neue) Farbe + */ + void FarbeSetzen (String farbe) + { + this.farbe = farbe; + symbol.FarbeSetzen(farbe); + } + + /** + * Setzt den Drehwinkel des Dreiecks. + * Die Winkelangabe ist in Grad,positive Werte drehen gegen den Uhrzeigersinn, + * negative Werte drehen im Uhrzeigersinn (mathematisch positiver Drehsinn). + * @param winkel der (neue) Drehwinkel des Dreiecks + */ + void WinkelSetzen (int winkel) + { + this.winkel = winkel; + symbol.WinkelSetzen(winkel); + } + + /** + * Schaltet die Sichtbarkeit des Dreiecks ein oder aus. + * Erlaubte Parameterwerte: true, false + * @param sichtbar (neue) Sichtbarkeit des Dreiecks + */ + void SichtbarkeitSetzen (boolean sichtbar) + { + this.sichtbar = sichtbar; + symbol.SichtbarkeitSetzen(sichtbar); + } + + /** + * Entfernt das Dreieck aus dem Zeichenfenster. + */ + void Entfernen () + { + symbol.Entfernen(); + } + + /** + * Bringt das Dreieck eine Ebene nach vorn. + */ + void NachVornBringen () + { + symbol.NachVornBringen(); + } + + /** + * Bringt das Dreieck in die vorderste Ebene. + */ + void GanzNachVornBringen () + { + symbol.GanzNachVornBringen(); + } + + /** + * Bringt das Dreieck eine Ebene nach hinten. + */ + void NachHintenBringen () + { + symbol.NachHintenBringen(); + } + + /** + * Bringt das Dreieck in die hinterste Ebene. + */ + void GanzNachHintenBringen () + { + symbol.GanzNachHintenBringen(); + } +} diff --git a/DreieckBesser.java b/DreieckBesser.java new file mode 100644 index 0000000..f729866 --- /dev/null +++ b/DreieckBesser.java @@ -0,0 +1,26 @@ + +/** + * Erlaubt das vollständige Anlegen im Konstruktor. + * + * @author Albert Wiedemann + * @version 1.0 + */ +class DreieckBesser extends Dreieck +{ + + /** + * Legt das Dreieck nach den gegebenen Daten an. + * @param x x-Position der Spitze + * @param y y-Position der Spitze + * @param breite Breite des Dreiecks + * @param höhe Höhe des Dreiecks + * @param farbe Farbe des Dreiecks + */ + DreieckBesser (int x, int y, int breite, int höhe, String farbe) + { + super(); + PositionSetzen(x, y); + GrößeSetzen(breite, höhe); + FarbeSetzen(farbe); + } +} diff --git a/Ereignisbehandlung.java b/Ereignisbehandlung.java new file mode 100644 index 0000000..8119639 --- /dev/null +++ b/Ereignisbehandlung.java @@ -0,0 +1,109 @@ +import java.awt.*; +import javax.swing.*; +import java.awt.event.*; + +/** + * Zugriff auf die Ereignisse einschließlich Taktgeber. + * + * @author Albert Wiedemann + * @version 1.0 + */ +public class Ereignisbehandlung +{ + /** + * Der Konstruktor meldet den Taktgeber + * und die Eventlistener bei der Zeichenfläche an. + */ + Ereignisbehandlung () + { + Zeichenfenster.AktionsEmpfängerEintragen(new Zeichenfenster.AktionsEmpfaenger() + { + public void Ausführen () + { + TaktImpulsAusführen(); + } + + public void Taste (char taste) + { + TasteGedrückt(taste); + } + + public void SonderTaste (int taste) + { + SonderTasteGedrückt(taste); + } + + public void Geklickt (int x, int y, int anzahl) + { + MausGeklickt(x, y, anzahl); + } + }); + } + + /** + * Die eigentliche Aktionsmethode des Zeitgebers. + *
Muss bei Bedarf von einer Unterklasse überschrieben werden. + */ + void TaktImpulsAusführen () + { + System.out.println ("Tick"); + } + + /** + * Zeitgeber starten. + */ + void Starten () + { + Zeichenfenster.TaktgeberStarten(); + } + + /** + * Zeitgeber anhalten. + */ + void Anhalten () + { + Zeichenfenster.TaktgeberStoppen(); + } + + /** + * Ablaufgeschwindigkeit des Zeitgebers einstellen. + * + * @param dauer: Angabe in Millisekunden + */ + void TaktdauerSetzen (int dauer) + { + Zeichenfenster.TaktdauerSetzen(dauer); + } + + /** + * Die eigentliche Aktionsmethode für gedrückte Tasten. + *
Muss bei Bedarf von einer Unterklasse überschrieben werden. + * @param taste die gedrückte Taste + */ + void TasteGedrückt (char taste) + { + System. out. println ("Taste: " + taste); + } + + /** + * Die eigentliche Aktionsmethode für gedrückte Sondertasten. + *
Muss bei Bedarf von einer Unterklasse überschrieben werden. + * @param taste KeyCode der gedrückten Taste + */ + void SonderTasteGedrückt (int taste) + { + System. out. println ("Sondertaste: " + taste); + } + + /** + * Die eigentliche Aktionsmethode für einen Mausklick. + *
Muss bei Bedarf von einer Unterklasse überschrieben werden. + * @param x x-Position des Mausklicks + * @param y y-Position des Mausklicks + * @param anzahl Anzahl der aufeinanderfolgenden Mausklicks + */ + void MausGeklickt (int x, int y, int anzahl) + { + System. out. println ("Maus: (" + x + "|" + y + "), " + anzahl + " mal"); + } +} diff --git a/Figur.java b/Figur.java new file mode 100644 index 0000000..e100c62 --- /dev/null +++ b/Figur.java @@ -0,0 +1,341 @@ + +/** + * Wrapperklasse für die Turtle auf der Zeichenfläche. + * + * @author Albert Wiedemann + * @version 1.0 + */ +public class Figur +{ + /** x-Position der Figur. */ + private int x; + /** y-Position der Figur. */ + private int y; + /** Größe der Figur. */ + private int größe; + /** Farbe der Figur. */ + private String farbe; + /** Sichtbarkeit der Figur. */ + private boolean sichtbar; + /** Drehwinkel (mathemtisch positiver Drehsinn) der Turtle in Grad. */ + private int winkel; + /** Referenz auf das echte Figursymbol. */ + Zeichenfenster.FigurIntern symbol; + /** Referenz auf das Aktionsempfängerobjekt. */ + Zeichenfenster.AktionsEmpfaenger aktionsEmpfänger; + + /** + * Konstruktor der Figur + * Erzeugt eine Figur und versetzt sie in einen gültigen Startzustand. + */ + Figur () + { + symbol = (Zeichenfenster.FigurIntern) Zeichenfenster.SymbolErzeugen(Zeichenfenster.SymbolArt.figur); + symbol.SichtbarkeitSetzen(true); + x = symbol.x; + y = symbol.y; + winkel = symbol.winkel; + größe = symbol.b; + sichtbar = symbol.sichtbar; + aktionsEmpfänger = new Zeichenfenster.AktionsEmpfaenger() + { + public void Ausführen () + { + AktionAusführen(); + } + + public void Taste (char taste) + { + TasteGedrückt(taste); + } + + public void SonderTaste (int taste) + { + SonderTasteGedrückt(taste); + } + + public void Geklickt (int x, int y, int anzahl) + { + MausGeklickt(x, y, anzahl); + } + }; + Zeichenfenster.AktionsEmpfängerEintragen(aktionsEmpfänger); + } + + /** + * Methode wird aufgerufen, wenn die Figur handeln soll. + * Die vordefinierte Methode tut nichts. + */ + void AktionAusführen() + { + } + + /** + * Die eigentliche Aktionsmethode für gedrückte Tasten. + *
Muss bei Bedarf von einer Unterklasse überschrieben werden. + * @param taste die gedrückte Taste + */ + void TasteGedrückt (char taste) + { + //System. out. println ("Taste: " + taste); + } + + /** + * Die eigentliche Aktionsmethode für gedrückte Sondertasten. + *
Muss bei Bedarf von einer Unterklasse überschrieben werden. + * @param taste KeyCode der gedrückten Taste + */ + void SonderTasteGedrückt (int taste) + { + //System. out. println ("Sondertaste: " + taste); + } + + /** + * Die eigentliche Aktionsmethode für einen Mausklick. + *
Muss bei Bedarf von einer Unterklasse überschrieben werden. + * @param x x-Position des Mausklicks + * @param y y-Position des Mausklicks + * @param anzahl Anzahl der aufeinanderfolgenden Mausklicks + */ + void MausGeklickt (int x, int y, int anzahl) + { + //System. out. println ("Maus: (" + x + "|" + y + "), " + anzahl + " mal"); + } + + /** + * Setzt die Position der Figur. + * @param x x-Position der Figur + * @param y y-Position der Figur + */ + void PositionSetzen(int x, int y) + { + this.x = x; + this.y = y; + symbol.PositionSetzen(x, y); + } + + /** + * Setzt die Größe des Figurensymbols. + * @param größe (neue) Größe + */ + void GrößeSetzen (int größe) + { + this.größe = größe; + symbol.GrößeSetzen(größe, größe); + } + + /** + * Setzt den Drehwinkel der Figur. + * Die Winkelangabe ist in Grad, positive Werte drehen gegen den Uhrzeigersinn, + * negative Werte drehen im Uhrzeigersinn (mathematisch positiver Drehsinn), d. h. + * 0˚: Figur schaut nach rechts, + * 90˚: Figur schaut nach oben, + * 180˚: Figur schaut nach links, + * 270˚bzw. -90˚: Figur schaut nach unten + * @param winkel der (neue) Drehwinkel der Figur + */ + void WinkelSetzen (int winkel) + { + this.winkel = winkel; + symbol.WinkelSetzen(winkel); + } + + /** + * Schaltet die Sichtbarkeit der Figur ein oder aus. + * Erlaubte Parameterwerte: true, false + * @param sichtbar (neue) Sichtbarkeit der Figur + */ + void SichtbarkeitSetzen (boolean sichtbar) + { + this.sichtbar = sichtbar; + symbol.SichtbarkeitSetzen(sichtbar); + } + + /** + * Entfernt die Figur aus dem Zeichenfenster. + */ + void Entfernen () + { + Zeichenfenster.AktionsEmpfängerEntfernen(aktionsEmpfänger); + symbol.Entfernen(); + } + + /** + * Bringt die Figur eine Ebene nach vorn. + */ + void NachVornBringen () + { + symbol.NachVornBringen(); + } + + /** + * Bringt die Figur in die vorderste Ebene. + */ + void GanzNachVornBringen () + { + symbol.GanzNachVornBringen(); + } + + /** + * Bringt die Figur eine Ebene nach hinten. + */ + void NachHintenBringen () + { + symbol.NachHintenBringen(); + } + + /** + * Bringt die Figur in die hinterste Ebene. + */ + void GanzNachHintenBringen () + { + symbol.GanzNachHintenBringen(); + } + + /** + * Setzt die Figur wieder an ihre Ausgangsposition. + */ + void ZumStartpunktGehen() + { + symbol.ZumStartpunktGehen(); + x = symbol.x; + y = symbol.y; + winkel = symbol.winkel; + } + + /** + * Bewegt die Figur nach vorne. + * @param länge Anzahl der Längeneinheiten + */ + void Gehen(double länge) + { + symbol.Gehen(länge); + x = symbol.x; + y = symbol.y; + } + + /** + * Dreht die Figur + * @param grad Drehwinkel (mathematisch positiver Drehsinn) im Gradmaß + */ + void Drehen(int grad) + { + symbol.Drehen(grad); + winkel = symbol.winkel; + } + + /** + * Gibt den aktuellen Winkel der Figur zurück. + * Die Winkelangabe ist in Grad, positive Werte drehen gegen den Uhrzeigersinn, + * negative Werte drehen im Uhrzeigersinn (mathematisch positiver Drehsinn), d. h. + * 0˚: Figur schaut nach rechts, + * 90˚: Figur schaut nach oben, + * 180˚: Figur schaut nach links, + * 270˚bzw. -90˚: Figur schaut nach unten + * @return Winkel im Gradmaß + */ + int WinkelGeben() + { + return winkel; + } + + /** + * Gibt die x-Koordinate der Figur zurück. + * @return x-Koordinate + */ + int XPositionGeben() + { + return x; + } + + /** + * Gibt die y-Koordinate der Figur zurück. + * @return y-Koordinate + */ + int YPositionGeben() + { + return y; + } + + /** + * Testet, ob die Figur eine Grafik-Figur berührt. + * @return true, wenn die Figur und eine Grafikfigur überlappen + */ + boolean Berührt () + { + return symbol.Berührt(); + } + + /** + * Testet, ob die Figur eine Grafik-Figur in der angegebenen Farbe berührt. + * @param farbe die Farbe, die die berührte Figur haben muss + * @return true, wenn die Figur und eine Grafikfigur in der angegebenen Farbe überlappen + */ + boolean Berührt (String farbe) + { + return symbol.Berührt(farbe); + } + + /** + * Testet, ob die Figur die angegebene Figur berührt. + * @param objekt das Objekt, das getestet werden soll + * @return true, wenn die Figur die angegebene Grafikfigur überlappen + */ + boolean Berührt (Object objekt) + { + return symbol.Berührt(objekt); + } + + /** + * Erzeugt ein neues, rechteckiges Element einer eigenen Darstellung der Figur. + * Alle Werte beziehen sich auf eine Figur der Größe 100x100 und den Koordinaten (0|0) in der Mitte des Quadrats + * @param x x-Wert der linken oberen Ecke des Rechtecks + * @param y y-Wert der linken oberen Ecke des Rechtecks + * @param breite Breite des Rechtecks + * @param höhe Höhe des Rechtecks + * @param farbe (Füll-)Farbe des Rechtecks + */ + void FigurteilFestlegenRechteck (int x, int y, int breite, int höhe, String farbe) + { + symbol.FigurteilFestlegenRechteck(x, y, breite, höhe, farbe); + } + + /** + * Erzeugt ein neues, elliptisches Element einer eigenen Darstellung der Figur. + * Alle Werte beziehen sich auf eine Figur der Größe 100x100 und den Koordinaten (0|0) in der Mitte des Quadrats + * @param x x-Wert der linken oberen Ecke des umgebenden Rechtecks der Ellipse + * @param y y-Wert der linken oberen Ecke des umgebenden Rechtecks der Ellipse + * @param breite Breite des umgebenden Rechtecks der Ellipse + * @param höhe Höhe des umgebenden Rechtecks der Ellipse + * @param farbe (Füll-)Farbe der Ellipse + */ + void FigurteilFestlegenEllipse (int x, int y, int breite, int höhe, String farbe) + { + symbol.FigurteilFestlegenEllipse(x, y, breite, höhe, farbe); + } + + /** + * Erzeugt ein neues, dreieckiges Element einer eigenen Darstellung der Figur. + * Alle Werte beziehen sich auf eine Figur der Größe 100x100 und den Koordinaten (0|0) in der Mitte des Quadrats + * @param x1 x-Wert des ersten Punkts des Dreiecks + * @param y1 y-Wert des ersten Punkts des Dreiecks + * @param x2 x-Wert des zweiten Punkts des Dreiecks + * @param y2 y-Wert des zweiten Punkts des Dreiecks + * @param x3 x-Wert des dritten Punkts des Dreiecks + * @param y3 y-Wert des dritten Punkts des Dreiecks + * @param farbe (Füll)Farbe des Dreiecks + */ + void FigurteilFestlegenDreieck (int x1, int y1, int x2, int y2, int x3, int y3, String farbe) + { + symbol.FigurteilFestlegenDreieck(x1, y1, x2, y2, x3, y3, farbe); + } + + /** + * Löscht die Vereinbarung für die eigene Darstellung der Figur. + * Die Figur wird wieder durch die Originalfigur dargestellt. + */ + void EigeneFigurLöschen() + { + symbol.EigeneFigurLöschen(); + } +} diff --git a/Kreis.java b/Kreis.java new file mode 100644 index 0000000..5a8f89a --- /dev/null +++ b/Kreis.java @@ -0,0 +1,166 @@ + +/** + * Wrapperklasse für einen Kreis auf der Zeichenfläche. + * + * @author Albert Wiedemann + * @version 1.0 + */ +public class Kreis +{ + /** x-Position des Kreismittelpunktes. */ + private int x; + /** y-Position des Kreismittelpunktes. */ + private int y; + /** Radius des Kreises. */ + private int radius; + /** Farbe des Kreises. */ + private String farbe; + /** Sichtbarkeit des Kreises. */ + private boolean sichtbar; + /** Drehwinkel (mathematisch positiver Drehsinn) des Kreises in Grad. */ + private int winkel; + /** Referenz auf das Delegate-Objekt. */ + Zeichenfenster.GrafikSymbol symbol; + + /** + * Der Konstruktor erzeugt das Delegate-Objekt + */ + Kreis () + { + x = 60; + y = 60; + radius = 50; + farbe = "rot"; + sichtbar = true; + winkel = 0; + symbol = Zeichenfenster.SymbolErzeugen(Zeichenfenster.SymbolArt.kreis); + symbol.PositionSetzen(x - radius, y - radius); + symbol.GrößeSetzen(radius * 2, radius * 2); + symbol.FarbeSetzen(farbe); + symbol.SichtbarkeitSetzen(sichtbar); + symbol.WinkelSetzen(winkel); + } + + /** + * Setzt die Position (des Mittelpunkts) des Kreises. + * @param x x-Position des Mittelpunkts + * @param y y-Position des Mittelpunkts + */ + void PositionSetzen(int x, int y) + { + this.x = x; + this.y = y; + symbol.PositionSetzen(x - radius, y - radius); + } + + /** + * Verschiebt den Kreis um die angegebenen Werte. + * @param deltaX Verschiebung in x-Richtung + * @param deltaY Verschiebung in y-Richtung + */ + void Verschieben(int deltaX, int deltaY) + { + x += deltaX; + y += deltaY; + symbol.PositionSetzen(x - radius, y - radius); + } + + /** + * Dreht den Kreis + * @param grad Drehwinkel (mathematisch positiver Drehsinn) im Gradmass + */ + void Drehen(int grad) + { + winkel += grad; + symbol.WinkelSetzen(winkel); + } + + /** + * Setzt den Radius des Kreises. + * @param radius (neuer) Radius + */ + void RadiusSetzen (int radius) + { + this.radius = radius; + symbol.GrößeSetzen(radius * 2, radius * 2); + symbol.PositionSetzen(x - radius, y - radius); + } + + /** + * Setzt die Farbe des Kreises. + * Erlaubte Farben sind: + * "weiß", "weiss", "rot", "grün", "gruen", "blau", "gelb", + * "magenta", "cyan", "hellgelb", "hellgrün", "hellgruen", + * "orange", "braun", "grau", "schwarz" + * Alle anderen Eingaben werden auf die Farbe schwarz abgebildet. + * @param farbe (neue) Farbe + */ + void FarbeSetzen (String farbe) + { + this.farbe = farbe; + symbol.FarbeSetzen(farbe); + } + + /** + * Setzt den Drehwinkel des Kreises. + * Die Winkelangabe ist in Grad,positive Werte drehen gegen den Uhrzeigersinn, + * negative Werte drehen im Uhrzeigersinn (mathematisch positiver Drehsinn). + * @param winkel der (neue) Drehwinkel des Kreises + */ + void WinkelSetzen (int winkel) + { + this.winkel = winkel; + symbol.WinkelSetzen(winkel); + } + + /** + * Schaltet die Sichtbarkeit des Kreises ein oder aus. + * Erlaubte Parameterwerte: true, false + * @param sichtbar (neue) Sichtbarkeit des Kreises + */ + void SichtbarkeitSetzen (boolean sichtbar) + { + this.sichtbar = sichtbar; + symbol.SichtbarkeitSetzen(sichtbar); + } + + /** + * Entfernt den Kreis aus dem Zeichenfenster. + */ + void Entfernen () + { + symbol.Entfernen(); + } + + /** + * Bringt den Kreis eine Ebene nach vorn. + */ + void NachVornBringen () + { + symbol.NachVornBringen(); + } + + /** + * Bringt den Kreis in die vorderste Ebene. + */ + void GanzNachVornBringen () + { + symbol.GanzNachVornBringen(); + } + + /** + * Bringt den Kreis eine Ebene nach hinten. + */ + void NachHintenBringen () + { + symbol.NachHintenBringen(); + } + + /** + * Bringt den Kreis in die hinterste Ebene. + */ + void GanzNachHintenBringen () + { + symbol.GanzNachHintenBringen(); + } +} diff --git a/KreisBesser.java b/KreisBesser.java new file mode 100644 index 0000000..839779e --- /dev/null +++ b/KreisBesser.java @@ -0,0 +1,25 @@ + +/** + * Erlaubt das vollständige Anlegen im Konstruktor. + * + * @author Albert Wiedemann + * @version 1.0 + */ +class KreisBesser extends Kreis +{ + + /** + * Legt den Kreis nach den gegebenen Daten an. + * @param x x-Position des Mittelpunkts + * @param y y-Position des Mittelpunkts + * @param radius Radius des Kreises + * @param farbe Farbe des Kreises + */ + KreisBesser (int x, int y, int radius, String farbe) + { + super(); + PositionSetzen(x, y); + RadiusSetzen(radius); + FarbeSetzen(farbe); + } +} diff --git a/README.TXT b/README.TXT new file mode 100644 index 0000000..323235f --- /dev/null +++ b/README.TXT @@ -0,0 +1,24 @@ +Projektbezeichnung: +Grafikdokument + +Ziel: +Ein erstes Einstiegsprojekt in die Entwicklungsumgebung BlueJ. +Dient zur Wiederholung der Begriffe Klasse, Objekt, Attribut, Methode, etc. +aus dem Informatikunterricht der Unterstufe. + +Man kann verschiedene Figuren erzeugen, die mit ihrem zugehörigen Grafiksymbol +in einem Grafikfenster eingezeichnet werden. + +Diese Figuren können durch den Aufruf von Methoden interaktiv verändert werden. +Nach jedem Methodenaufruf wird das Grafiksymbol und damit die ganze Zeichnung +automatisch angepasst. + +Start des Projekts: +Erzeugen neuer Figur-Objekte über das Kontextmenü. + +Version: +1.0 + +Autor: +A. Wiedemann + diff --git a/Rechteck.java b/Rechteck.java new file mode 100644 index 0000000..9931e5c --- /dev/null +++ b/Rechteck.java @@ -0,0 +1,170 @@ + +/** + * Wrapperklasse für ein Rechteck auf der Zeichenfläche. + * + * @author Albert Wiedemann + * @version 1.0 + */ +public class Rechteck +{ + /** x-Position der linken oberen Ecke. */ + private int x; + /** y-Position der linken oberen Ecke. */ + private int y; + /** Breite des Rechtecks. */ + private int breite; + /** Höhe des Rechtecks. */ + private int höhe; + /** Farbe des Rechtecks. */ + private String farbe; + /** Sichtbarkeit des Rechtecks. */ + private boolean sichtbar; + /** Drehwinkel (mathematisch positiver Drehsinn) des Rechtecks in Grad. */ + private int winkel; + /** Referenz auf das Delegate-Objekt. */ + Zeichenfenster.GrafikSymbol symbol; + + /** + * Der Konstruktor erzeugt das Delegate-Objekt + */ + Rechteck () + { + x = 10; + y = 10; + breite = 100; + höhe = 100; + farbe = "rot"; + sichtbar = true; + winkel = 0; + symbol = Zeichenfenster.SymbolErzeugen(Zeichenfenster.SymbolArt.rechteck); + symbol.PositionSetzen(x, y); + symbol.GrößeSetzen(breite, höhe); + symbol.FarbeSetzen(farbe); + symbol.SichtbarkeitSetzen(sichtbar); + symbol.WinkelSetzen(winkel); + } + + /** + * Setzt die Position (der linken oberen Ecke) des Rechtecks. + * @param x x-Position der linken oberen Ecke + * @param y y-Position der linken oberen Ecke + */ + void PositionSetzen(int x, int y) + { + this.x = x; + this.y = y; + symbol.PositionSetzen(x, y); + } + + /** + * Verschiebt das Rechteck um die angegebenen Werte. + * @param deltaX Verschiebung in x-Richtung + * @param deltaY Verschiebung in y-Richtung + */ + void Verschieben(int deltaX, int deltaY) + { + x += deltaX; + y += deltaY; + symbol.PositionSetzen(x, y); + } + + /** + * Dreht das Rechteck + * @param grad Drehwinkel (mathematisch positiver Drehsinn) im Gradmass + */ + void Drehen(int grad) + { + winkel += grad; + symbol.WinkelSetzen(winkel); + } + + /** + * Setzt die Größe des Rechtecks. + * @param breite (neue) Breite + * @param höhe (neue) Höhe + */ + void GrößeSetzen (int breite, int höhe) + { + this.breite = breite; + this.höhe = höhe; + symbol.GrößeSetzen(breite, höhe); + } + + /** + * Setzt die Farbe des Rechtecks. + * Erlaubte Farben sind: + * "weiß", "weiss", "rot", "grün", "gruen", "blau", "gelb", + * "magenta", "cyan", "hellgelb", "hellgrün", "hellgruen", + * "orange", "braun", "grau", "schwarz" + * Alle anderen Eingaben werden auf die Farbe schwarz abgebildet. + * @param farbe (neue) Farbe + */ + void FarbeSetzen (String farbe) + { + this.farbe = farbe; + symbol.FarbeSetzen(farbe); + } + + /** + * Setzt den Drehwinkel des Rechtecks. + * Die Winkelangabe ist in Grad,positive Werte drehen gegen den Uhrzeigersinn, + * negative Werte drehen im Uhrzeigersinn (mathematisch positiver Drehsinn). + * @param winkel der (neue) Drehwinkel des Rechtecks + */ + void WinkelSetzen (int winkel) + { + this.winkel = winkel; + symbol.WinkelSetzen(winkel); + } + + /** + * Schaltet die Sichtbarkeit des Rechtecks ein oder aus. + * Erlaubte Parameterwerte: true, false + * @param sichtbar (neue) Sichtbarkeit des Rechtecks + */ + void SichtbarkeitSetzen (boolean sichtbar) + { + this.sichtbar = sichtbar; + symbol.SichtbarkeitSetzen(sichtbar); + } + + /** + * Entfernt das Rechteck aus dem Zeichenfenster. + */ + void Entfernen () + { + symbol.Entfernen(); + } + + /** + * Bringt das Rechteck eine Ebene nach vorn. + */ + void NachVornBringen () + { + symbol.NachVornBringen(); + } + + /** + * Bringt das Rechteck in die vorderste Ebene. + */ + void GanzNachVornBringen () + { + symbol.GanzNachVornBringen(); + } + + /** + * Bringt das Rechteck eine Ebene nach hinten. + */ + void NachHintenBringen () + { + symbol.NachHintenBringen(); + } + + /** + * Bringt das Rechteck in die hinterste Ebene. + */ + void GanzNachHintenBringen () + { + symbol.GanzNachHintenBringen(); + } +} diff --git a/RechteckBesser.java b/RechteckBesser.java new file mode 100644 index 0000000..f98f471 --- /dev/null +++ b/RechteckBesser.java @@ -0,0 +1,26 @@ + +/** + * Erlaubt das vollständige Anlegen im Konstruktor. + * + * @author Albert Wiedemann + * @version 1.0 + */ +class RechteckBesser extends Rechteck +{ + + /** + * Legt das Rechteck nach den gegebenen Daten an. + * @param x x-Position der linken oberen Ecke + * @param y y-Position der linken oberen Ecke + * @param breite Breite des Rechtecks + * @param höhe Höhe des Rechtecks + * @param farbe Farbe des Rechtecks + */ + RechteckBesser (int x, int y, int breite, int höhe, String farbe) + { + super(); + PositionSetzen(x, y); + GrößeSetzen(breite, höhe); + FarbeSetzen(farbe); + } +} diff --git a/Text.java b/Text.java new file mode 100644 index 0000000..8a4c660 --- /dev/null +++ b/Text.java @@ -0,0 +1,193 @@ + +/** + * Wrapperklasse für einen Text auf der Zeichenfläche. + * + * @author Albert Wiedemann + * @version 1.0 + */ +public class Text +{ + /** x-Position der linken Seite der Grundlinie. */ + private int x; + /** y-Position der Grundlinie. */ + private int y; + /** Farbe des Textes. */ + private String farbe; + /** Sichtbarkeit des Textes. */ + private boolean sichtbar; + /** Drehwinkel (mathematisch positiver Drehsinn) des Textes in Grad. */ + private int winkel; + /** Größe des Textes in Punkten. */ + private int textgröße; + + /** Referenz auf das Delegate-Objekt. */ + private Zeichenfenster.TextIntern symbol; + + /** + * Der Konstruktor erzeugt das Delegate-Objekt + */ + Text () + { + x = 10; + y = 10; + farbe = "schwarz"; + sichtbar = true; + winkel = 0; + textgröße = 12; + symbol = (Zeichenfenster.TextIntern) Zeichenfenster.SymbolErzeugen(Zeichenfenster.SymbolArt.text); + symbol.PositionSetzen(x, y); + symbol.FarbeSetzen(farbe); + symbol.SichtbarkeitSetzen(sichtbar); + symbol.WinkelSetzen(winkel); + symbol.TextGrößeSetzen(textgröße); + } + + /** + * Setzt die Position (der Grundline) des Textes. + * @param x x-Position der linken Seite der Grundlinie + * @param y y-Position der Grundlinie + */ + void PositionSetzen(int x, int y) + { + this.x = x; + this.y = y; + symbol.PositionSetzen(x, y); + } + + /** + * Setzt den aktuellen Text. + * @param text der neue Text + */ + void TextSetzen (String text) + { + symbol.TextSetzen(text); + } + + /** + * Setzt die Größe des Textes. + * @param größe die (neue) Textgröße + */ + void TextGrößeSetzen (int größe) + { + textgröße = größe; + symbol.TextGrößeSetzen(größe); + } + + /** + * Vergrößert den Text. + */ + void TextVergrößern() + { + symbol.TextVergrößern(); + textgröße = (int) symbol.size; + } + + /** + * Verkleinert den Text. + */ + void TextVerkleinern() + { + symbol.TextVerkleinern(); + textgröße = (int) symbol.size; + } + + /** + * Verschiebt den Text um die angegebenen Werte. + * @param deltaX Verschiebung in x-Richtung + * @param deltaY Verschiebung in y-Richtung + */ + void Verschieben(int deltaX, int deltaY) + { + x += deltaX; + y += deltaY; + symbol.PositionSetzen(x, y); + } + + /** + * Dreht den Text + * @param grad Drehwinkel (mathematisch positiver Drehsinn) im Gradmass + */ + void Drehen(int grad) + { + winkel += grad; + symbol.WinkelSetzen(winkel); + } + + /** + * Setzt die Farbe des Textes. + * Erlaubte Farben sind: + * "weiß", "weiss", "rot", "grün", "gruen", "blau", "gelb", + * "magenta", "cyan", "hellgelb", "hellgrün", "hellgruen", + * "orange", "braun", "grau", "schwarz" + * Alle anderen Eingaben werden auf die Farbe schwarz abgebildet. + * @param farbe (neue) Farbe + */ + void FarbeSetzen (String farbe) + { + this.farbe = farbe; + symbol.FarbeSetzen(farbe); + } + + /** + * Setzt den Drehwinkel des Textes. + * Die Winkelangabe ist in Grad,positive Werte drehen gegen den Uhrzeigersinn, + * negative Werte drehen im Uhrzeigersinn (mathematisch positiver Drehsinn). + * @param winkel der (neue) Drehwinkel des Textes + */ + void WinkelSetzen (int winkel) + { + this.winkel = winkel; + symbol.WinkelSetzen(winkel); + } + + /** + * Schaltet die Sichtbarkeit des Textes ein oder aus. + * Erlaubte Parameterwerte: true, false + * @param sichtbar (neue) Sichtbarkeit des Textes + */ + void SichtbarkeitSetzen (boolean sichtbar) + { + this.sichtbar = sichtbar; + symbol.SichtbarkeitSetzen(sichtbar); + } + + /** + * Entfernt den Text aus dem Zeichenfenster. + */ + void Entfernen () + { + symbol.Entfernen(); + } + + /** + * Bringt den Text eine Ebene nach vorn. + */ + void NachVornBringen () + { + symbol.NachVornBringen(); + } + + /** + * Bringt den Text in die vorderste Ebene. + */ + void GanzNachVornBringen () + { + symbol.GanzNachVornBringen(); + } + + /** + * Bringt den Text eine Ebene nach hinten. + */ + void NachHintenBringen () + { + symbol.NachHintenBringen(); + } + + /** + * Bringt den Text in die hinterste Ebene. + */ + void GanzNachHintenBringen () + { + symbol.GanzNachHintenBringen(); + } +} diff --git a/Turtle.java b/Turtle.java new file mode 100644 index 0000000..b0815f5 --- /dev/null +++ b/Turtle.java @@ -0,0 +1,342 @@ + +/** + * Wrapperklasse für die Turtle auf der Zeichenfläche. + * + * @author Albert Wiedemann + * @version 1.0 + */ +public class Turtle +{ + /** x-Position der Turtle. */ + private int x; + /** y-Position der Turtle. */ + private int y; + /** Größe der Turtle. */ + private int größe; + /** Farbe der Turtle. */ + private String farbe; + /** Sichtbarkeit der Turtles. */ + private boolean sichtbar; + /** Drehwinkel (mathemtisch positiver Drehsinn) der Turtle in Grad. */ + private int winkel; + /**Stiftposition*/ + private boolean stiftUnten; + /** Referenz auf das echte Turtlesybol. */ + Zeichenfenster.TurtleIntern symbol; + /** Referenz auf das Aktionsempfängerobjekt. */ + Zeichenfenster.AktionsEmpfaenger aktionsEmpfänger; + + /** + * Konstruktor der Turtle + * Erzeugt eine Turtle und versetzt sie in einen gültigen Startzustand. + */ + Turtle () + { + symbol = (Zeichenfenster.TurtleIntern) Zeichenfenster.SymbolErzeugen(Zeichenfenster.SymbolArt.turtle); + symbol.SichtbarkeitSetzen(true); + x = symbol.x; + y = symbol.y; + winkel = symbol.winkel; + größe = symbol.b; + stiftUnten = symbol.stiftUnten; + sichtbar = symbol.sichtbar; + aktionsEmpfänger = new Zeichenfenster.AktionsEmpfaenger() + { + public void Ausführen () + { + AktionAusführen(); + } + + public void Taste (char taste) + { + TasteGedrückt(taste); + } + + public void SonderTaste (int taste) + { + SonderTasteGedrückt(taste); + } + + public void Geklickt (int x, int y, int anzahl) + { + MausGeklickt(x, y, anzahl); + } + }; + Zeichenfenster.AktionsEmpfängerEintragen(aktionsEmpfänger); + } + + /** + * Methode wird aufgerufen, wenn die Turtle handeln soll. + * Die vordefinierte Methode tut nichts. + */ + void AktionAusführen() + { + } + + /** + * Die eigentliche Aktionsmethode für gedrückte Tasten. + *
Muss bei Bedarf von einer Unterklasse überschrieben werden. + * @param taste die gedrückte Taste + */ + void TasteGedrückt (char taste) + { + //System. out. println ("Taste: " + taste); + } + + /** + * Die eigentliche Aktionsmethode für gedrückte Sondertasten. + *
Muss bei Bedarf von einer Unterklasse überschrieben werden. + * @param taste KeyCode der gedrückten Taste + */ + void SonderTasteGedrückt (int taste) + { + //System. out. println ("Sondertaste: " + taste); + } + + /** + * Die eigentliche Aktionsmethode für einen Mausklick. + *
Muss bei Bedarf von einer Unterklasse überschrieben werden. + * @param x x-Position des Mausklicks + * @param y y-Position des Mausklicks + * @param anzahl Anzahl der aufeinanderfolgenden Mausklicks + */ + void MausGeklickt (int x, int y, int anzahl) + { + System. out. println ("Maus: (" + x + "|" + y + "), " + anzahl + " mal"); + } + + /** + * Setzt die Position der Turtle. + * @param x x-Position der Turtle + * @param y y-Position der Turtle + */ + void PositionSetzen(int x, int y) + { + this.x = x; + this.y = y; + symbol.PositionSetzen(x, y); + } + + /** + * Setzt die Größe des Turtlesymbols. + * @param größe (neue) Größe + */ + void GrößeSetzen (int größe) + { + this.größe = größe; + symbol.GrößeSetzen(größe, größe); + } + + /** + * Setzt die Farbe der Linie. + * Erlaubte Farben sind: + * "weiß", "weiss", "rot", "grün", "gruen", "blau", "gelb", + * "magenta", "cyan", "hellgelb", "hellgrün", "hellgruen", + * "orange", "braun", "grau", "schwarz" + * Alle anderen Eingaben werden auf die Farbe schwarz abgebildet. + * @param farbe (neue) Farbe + */ + void FarbeSetzen (String farbe) + { + this.farbe = farbe; + symbol.FarbeSetzen(farbe); + } + + /** + * Setzt den Drehwinkel der Turtle. + * Die Winkelangabe ist in Grad, positive Werte drehen gegen den Uhrzeigersinn, + * negative Werte drehen im Uhrzeigersinn (mathematisch positiver Drehsinn), d. h. + * 0˚: Turtle schaut nach rechts, + * 90˚: Turtle schaut nach oben, + * 180˚: Turtle schaut nach links, + * 270˚bzw. -90˚: Turtle schaut nach unten + * @param winkel der (neue) Drehwinkel der Turtle + */ + void WinkelSetzen (int winkel) + { + this.winkel = winkel; + symbol.WinkelSetzen(winkel); + } + + /** + * Schaltet die Sichtbarkeit der Turtle ein oder aus. + * Erlaubte Parameterwerte: true, false + * @param sichtbar (neue) Sichtbarkeit der Turtle + */ + void SichtbarkeitSetzen (boolean sichtbar) + { + this.sichtbar = sichtbar; + symbol.SichtbarkeitSetzen(sichtbar); + } + + /** + * Entfernt die Turtle aus dem Zeichenfenster. + */ + void Entfernen () + { + Zeichenfenster.AktionsEmpfängerEntfernen(aktionsEmpfänger); + symbol.Entfernen(); + } + + /** + * Bringt die Turtle eine Ebene nach vorn. + */ + void NachVornBringen () + { + symbol.NachVornBringen(); + } + + /** + * Bringt die Turtle in die vorderste Ebene. + */ + void GanzNachVornBringen () + { + symbol.GanzNachVornBringen(); + } + + /** + * Bringt die Turtle eine Ebene nach hinten. + */ + void NachHintenBringen () + { + symbol.NachHintenBringen(); + } + + /** + * Bringt die Turtle in die hinterste Ebene. + */ + void GanzNachHintenBringen () + { + symbol.GanzNachHintenBringen(); + } + + /** + * Setzt die Turtle wieder an ihre Ausgangsposition. + */ + void ZumStartpunktGehen() + { + symbol.ZumStartpunktGehen(); + x = symbol.x; + y = symbol.y; + winkel = symbol.winkel; + } + + /** + * Bewegt die Turtle nach vorne. + * @param länge Anzahl der Längeneinheiten + */ + void Gehen(double länge) + { + symbol.Gehen(länge); + x = symbol.x; + y = symbol.y; + } + + /** + * Dreht die Turtle + * @param grad Drehwinkel (mathematisch positiver Drehsinn) im Gradmaß + */ + void Drehen(int grad) + { + symbol.Drehen(grad); + winkel = symbol.winkel; + } + + /** + * Versetzt Zeichenfläche und Turtle in den Ausgangszustand + */ + void Löschen() + { + symbol.Löschen(); + } + + /** + * Turtle wechselt in den Modus "nicht zeichnen" + */ + void StiftHeben() + { + symbol.StiftHeben(); + stiftUnten = false; + } + + /** + * Turtle wechselt in den Modus "zeichnen" + */ + void StiftSenken() + { + symbol.StiftSenken(); + stiftUnten = true; + } + + /** + * Gibt den aktuellen Winkel der Turtle zurück. + * Die Winkelangabe ist in Grad, positive Werte drehen gegen den Uhrzeigersinn, + * negative Werte drehen im Uhrzeigersinn (mathematisch positiver Drehsinn), d. h. + * 0˚: Turtle schaut nach rechts, + * 90˚: Turtle schaut nach oben, + * 180˚: Turtle schaut nach links, + * 270˚bzw. -90˚: Turtle schaut nach unten + * @return Winkel im Gradmass + */ + int WinkelGeben() + { + return winkel; + } + + /** + * Gibt die x-Koordinate der Turtle zurück + * @return x-Koordinate + */ + int XPositionGeben() + { + return x; + } + + /** + * Gibt die y-Koordinate der Turtle zurück + * @return y-Koordinate + */ + int YPositionGeben() + { + return y; + } + + /** + * Schaltet die Sichtbarkeit des Turtlesymbols ein oder aus. + * Erlaubte Parameterwerte: true, false + * @param sichtbar (neue) Sichtbarkeit des Turtlesymbols + */ + void SichtbarkeitFürSymbolSetzen (boolean sichtbar) + { + symbol.SichtbarkeitFürSymbolSetzen(sichtbar); + } + + /** + * Testet, ob die Turtle eine Figur berührt. + * @return true, wenn die Turtlekoordinaten innerhalb einer Grafikfigur sind + */ + boolean Berührt () + { + return symbol.Berührt(); + } + + /** + * Testet, ob die Turtle eine Figur in der angegebenen Farbe berührt. + * @param farbe die Farbe, die die berührte Figur haben muss. + * @return true, wenn die Turtlekoordinaten innerhalb einer Grafikfigur in der angegebenen Farbe sind + */ + boolean Berührt (String farbe) + { + return symbol.Berührt(farbe); + } + + /** + * Testet, ob die Turtle die angegebene Figur berührt. + * @param objekt das Objekt, das getestet werden soll. + * @return true, wenn die Turtlekoordinaten innerhalb der angegebenen Grafikfigur sind + */ + boolean Berührt (Object objekt) + { + return symbol.Berührt(objekt); + } +} diff --git a/Zeichenfenster.java b/Zeichenfenster.java new file mode 100644 index 0000000..ecf129a --- /dev/null +++ b/Zeichenfenster.java @@ -0,0 +1,1864 @@ + +import java.awt.*; +import java.awt.geom.*; +import java.awt.event.*; +import java.awt.image.*; +import javax.swing.*; +import javax.swing.event.*; +import java.util.*; +/** + * Die Klasse stellt ein Fenster mit einer Malfläche zur Verfügung, + * auf der Objekte der Klassen Rechteck, Kreis und Dreieck sowie Turtle dargestellt + * werden können. + * Die Zeichenfläche wird beim ersten Anlegen eines Zeichenobjekts automatisch + * nach dem Muster Singleton angelegt. + * + * @author Albert Wiedemann + * @version 1.0 + */ +class Zeichenfenster +{ + /** Interface für die Aktionsausführung. */ + interface AktionsEmpfaenger + { + /** Methode wird vom Taktgeber aufgerufen. */ + void Ausführen(); + void Taste (char taste); + void SonderTaste (int taste); + void Geklickt (int x, int y, int anzahl); + } + + /** Aufzählung der erzeugbaren Objektarten. */ + static enum SymbolArt {kreis, dreieck, rechteck, turtle, figur, text;}; + + /** Einziges Objekt der Zeichenfläche. */ + private static Zeichenfenster zeichenfläche = null; + + /** Fenster für die Zeichenfläche. */ + private JFrame fenster; + /** Die eigentliche Darstellungskomponente. */ + private JComponent malfläche; + /** Stop-Knopf für den Taktgeber. */ + private JButton stop; + /** Start-Knopf für den Taktgeber. */ + private JButton start; + /** Einsteller für die Taktrate*/ + private JSlider slider; + /** Feld aller zu zeichnenden Objekte. */ + private ArrayList alleSymbole; + /** Feld aller zu zeichnenden Objekte. */ + private ArrayList aktionsEmpfänger; + /** Timerobjekt für die zentrale Zeitverwaltung */ + private javax.swing.Timer timer; + + /** + * Legt das Fenster und die Malfläche an + */ + private Zeichenfenster () + { + alleSymbole = new ArrayList(); + aktionsEmpfänger = new ArrayList(); + fenster = new JFrame("Zeichenfenster"); + fenster.setLocation(50, 50); + fenster.setSize(800, 600); + fenster.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); //Close-Button kann nicht versteckt oder abgestellt werden. + + malfläche = new JComponent() + { + public void paint (Graphics g) + { + g.setColor(new Color (230, 230, 230)); + g.fillRect(0, 0, getWidth() - 1, getHeight() - 1); + synchronized (malfläche) + { + for (GrafikSymbol s: alleSymbole) + { + if (s.sichtbar) + { + s.Zeichnen(g); + } + } + } + } + }; + malfläche.setOpaque(true); + malfläche.addMouseListener(new MouseAdapter () + { + /** + * Gibt den Ort eines Mouseclicks an die eigentliche Aktionsmethode weiter. + * @param e das zugrestellte Ereignis + */ + public void mousePressed(MouseEvent e) + { + malfläche.requestFocus(); + ArrayList empfänger = new ArrayList(aktionsEmpfänger); + for (AktionsEmpfaenger em: empfänger) + { + em.Geklickt(e.getX(), e.getY(), e.getClickCount()); + } + } + } + ); + malfläche.addKeyListener(new KeyAdapter () + { + /** + * Gibt die Taste an die eigentliche Aktionsmethode weiter. + * @param e das zugestellte Ereignis + */ + public void keyPressed(KeyEvent e) + { + ArrayList empfänger = new ArrayList(aktionsEmpfänger); + if ((int) e.getKeyChar() == KeyEvent.CHAR_UNDEFINED) + { + switch (e.getKeyCode()) + { + case KeyEvent.VK_ENTER: + for (AktionsEmpfaenger em: empfänger) + { + em.Taste((char) KeyEvent.VK_ENTER); + } + break; + default: + for (AktionsEmpfaenger em: empfänger) + { + em.SonderTaste(e.getKeyCode()); + } + } + } + else + { + for (AktionsEmpfaenger em: empfänger) + { + em.Taste(e.getKeyChar()); + } + } + } + } + ); + malfläche.addComponentListener(new ComponentAdapter() + { + /** + * Setzt die Hintegrundbilder aller Turtle auf die neue Größe. + */ + public void componentResized​(ComponentEvent e) + { + for (GrafikSymbol s: alleSymbole) + { + if (s instanceof TurtleIntern) + { + ((TurtleIntern) s).NeueGrößeSetzen(); + } + } + } + } + ); + fenster.add(malfläche, BorderLayout.CENTER); + JPanel panel = new JPanel(); + panel.setMinimumSize(new Dimension(200, 60)); + panel.setSize(200,60); + panel.setVisible(true); + panel.setLayout(new GridLayout(1, 2)); + JPanel panel2 = new JPanel(); + panel2.setMinimumSize(new Dimension(100, 60)); + panel2.setSize(100,60); + panel2.setVisible(true); + panel2.setLayout(new GridLayout(1, 1)); + stop = new JButton(); + start = new JButton(); + start.setLocation(10, 10); + start.setSize(80, 30); + start.setText("Start"); + start.setVisible(true); + start.addActionListener(new ActionListener () + { + public void actionPerformed (ActionEvent evt) + { + TaktgeberStartenIntern(); + malfläche.requestFocus(); + } + } + ); + panel2.add(start); + stop.setLocation(100, 10); + stop.setSize(80, 30); + stop.setText("Stop"); + stop.setVisible(true); + stop.setEnabled(false); + stop.addActionListener(new ActionListener () + { + public void actionPerformed (ActionEvent evt) + { + TaktgeberStoppenIntern(); + malfläche.requestFocus(); + } + } + ); + panel2.add(stop); + panel.add(panel2); + slider = new JSlider(0, 1000, 100); + slider.setLocation(190, 10); + slider.setSize(160, 40); + slider.setMinimumSize(new Dimension(160, 40)); + slider.setPreferredSize(new Dimension(160, 40)); + slider.setMajorTickSpacing(100); + slider.setPaintTicks(true); + slider.setPaintLabels(true); + slider.setValue(1000); + slider.addChangeListener(new ChangeListener() + { + public void stateChanged​(ChangeEvent e) + { + timer.setDelay(slider.getValue()); + malfläche.requestFocus(); + } + } + ); + panel.add(slider); + + fenster.add(panel, BorderLayout.SOUTH); + fenster.setVisible(true); + malfläche.requestFocus(); + + timer = new javax.swing.Timer (1000, new ActionListener () + { + /** + * Vom Timer aufgerufen. + * Erzeugt den nächsten Taktimpuls + * @param evt der Timerevent + */ + public void actionPerformed (ActionEvent evt) + { + ArrayList empfänger = new ArrayList(aktionsEmpfänger); + for (AktionsEmpfaenger e: empfänger) + { + e.Ausführen(); + } + } + } + ); + } + + /** + * Meldet die aktuelle Breite der Malfläche. + * @returns Breite der Malfläche + */ + static int MalflächenBreiteGeben() + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + return zeichenfläche.malfläche.getWidth(); + } + + /** + * Meldet die aktuelle Höhe der Malfläche. + * @returns Höhe der Malfläche + */ + static int MalflächenHöheGeben() + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + return zeichenfläche.malfläche.getHeight(); + } + + /** + * Trägt einen neuen Aktionsempfänger ein. + * @param neu der neue Aktionsempfänger + */ + static void AktionsEmpfängerEintragen(AktionsEmpfaenger neu) + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + zeichenfläche.aktionsEmpfänger.add(neu); + } + + /** + * Löscht einen Aktionsempfänger aus der Liste. + * @param alt der zu löschende Aktionsempfänger + */ + static void AktionsEmpfängerEntfernen(AktionsEmpfaenger alt) + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + zeichenfläche.aktionsEmpfänger.remove(alt); + } + + /** + * Erzeugt ein neues darzustelledes Symbol. + * Die möglichen Symbole sind im Aufzählungstyp SymbolArt beschrieben. + * @param art Art des zu erzeugenden Symbols. + * @return Referenz auf das Delegate-Objekt. + */ + static GrafikSymbol SymbolErzeugen (SymbolArt art) + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + return zeichenfläche.SymbolAnlegen(art); + } + + /** + * Startet den Taktgeber. + */ + static void TaktgeberStarten () + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + zeichenfläche.TaktgeberStartenIntern(); + } + + /** + * Stoppt den Taktgeber. + */ + static void TaktgeberStoppen () + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + zeichenfläche.TaktgeberStoppenIntern(); + } + + /** + * Ablaufgeschwindigkeit des Zeitgebers einstellen. + * + * @param dauer: Angabe in Millisekunden + */ + static void TaktdauerSetzen (int dauer) + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + zeichenfläche.slider.setValue(dauer < 0 ? 0 : (dauer > 1000 ? 1000: dauer)); + } + + /** + * Erzeugt das neue Symbol tatsächlich. + * @param art Art des zu erzeugenden Symbols. + * @return Referenz auf das Delegate-Objekt. + */ + private GrafikSymbol SymbolAnlegen (SymbolArt art) + { + GrafikSymbol neu = null; + switch (art) + { + case rechteck: + neu = new RechteckIntern(); + break; + case kreis: + neu = new EllipseIntern(); + break; + case dreieck: + neu = new DreieckIntern(); + break; + case turtle: + neu = new TurtleIntern(); + break; + case figur: + neu = new FigurIntern(); + break; + case text: + neu = new TextIntern(); + break; + } + synchronized (zeichenfläche.malfläche) + { + zeichenfläche.alleSymbole.add(neu); + } + malfläche.repaint(); + return neu; + } + + /** + * Startet den Taktgeber. + */ + private void TaktgeberStartenIntern() + { + start.setEnabled(false); + stop.setEnabled(true); + timer.start(); + } + + /** + * Stoppt den Taktgeber. + */ + private void TaktgeberStoppenIntern() + { + start.setEnabled(true); + stop.setEnabled(false); + timer.stop(); + } + + /** + * Oberklasse für alle verfügbaren Grafiksymbole. + * Alle Grafiksymbole werden über ihr umgebendes Rechteck beschrieben. + */ + abstract class GrafikSymbol + { + /** x-Position der linken oberen Ecke. */ + protected int x; + /** y-Position der linken oberen Ecke. */ + protected int y; + /** Breite des umgebenden Rechtecks. */ + protected int b; + /** Höhe des umgebenden Rechtecks. */ + protected int h; + /** Farbe des Symbols. */ + protected Color c; + /** Sichtbarkeit des Symbols. */ + protected boolean sichtbar; + /** Drehwinkel (mathematisch positiver Drehsinn) des Symbols. */ + protected int winkel; + /** Die Form des Grafiksymbols. */ + protected Area form; + /** Farbe Hellgelb. */ + protected final Color hellgelb = new Color(255,255,128); + /** Farbe Hellgrün. */ + protected final Color hellgrün = new Color(128,255,128); + /** Farbe Orange. */ + protected final Color orange = new Color(255,128,0); + /** Farbe Braun. */ + protected final Color braun = new Color(128,64,0); + + /** + * Der Konstruktor erzeugt ein rotes Symbol in der linken oberen Ecke des Fensters. + */ + GrafikSymbol() + { + x = 10; + y = 10; + b = 100; + h = 100; + c = Color.RED; + sichtbar = true; + winkel = 0; + FormErzeugen(); + } + + /** + * Normiert den Winkel auf Werte im Bereich [0; 360[ + * @param winkel der Eingabewinkel + * @return der normierte Winkel + */ + int WinkelNormieren(int winkel) + { + while (winkel < 0) + { + winkel += 360; + } + return winkel % 360; + } + + /** + * Setzt die Position (der linken oberen Ecke) des Objekts. + * @param x x-Position der linken oberen Ecke + * @param y y-Position der linken oberen Ecke + */ + void PositionSetzen (int x, int y) + { + this.x = x; + this.y = y; + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Setzt die Größe des Objekts. + * @param breite (neue) Breite des Objekts + * @param höhe (neue) Höhe des Objekts + */ + void GrößeSetzen (int breite, int höhe) + { + b = breite; + h = höhe; + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Bestimmt die RGB-Farbe für den gegeben String. + * @param farbe die Farbe als String + * @return die Farbe als RGB-Farbe + */ + Color FarbeCodieren (String farbe) + { + farbe = farbe.toLowerCase(); + switch (farbe) + { + case "weiß": + case "weiss": + return Color.WHITE; + case "rot": + return Color.RED; + case "grün": + case "gruen": + return Color.GREEN; + case "blau": + return Color.BLUE; + case "gelb": + return Color.YELLOW; + case "magenta": + return Color.MAGENTA; + case "cyan": + return Color.CYAN; + case "hellgelb": + return hellgelb; + case "hellgrün": + case "hellgruen": + return hellgrün; + case "orange": + return orange; + case "braun": + return braun; + case "grau": + return Color.GRAY; + case "schwarz": + return Color.BLACK; + default: + return Color.BLACK; + } + } + + /** + * Setzt die Farbe des Objekts. + * @param farbe (neue) Farbe des Objekts + */ + void FarbeSetzen (String farbe) + { + FarbeSetzen(FarbeCodieren(farbe)); + } + + /** + * Setzt die Farbe des Objekts. + * @param c (neue) Farbe des Objekts + */ + void FarbeSetzen (Color c) + { + this.c = c; + zeichenfläche.malfläche.repaint(); + } + + /** + * Setzt die Sichtbarkeit des Objekts. + * @param sichtbar (neue) Sichtbarkeit des Objekts + */ + void SichtbarkeitSetzen (boolean sichtbar) + { + this.sichtbar = sichtbar; + zeichenfläche.malfläche.repaint(); + } + + /** + * Setzt den Drehwinkel des Objekts. + * @param winkel der (neue) Drehwinkel des Objekts + */ + void WinkelSetzen (int winkel) + { + this.winkel = WinkelNormieren(winkel); + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Entfernt das Objekt aus dem Zeichenfenster. + */ + void Entfernen () + { + synchronized (zeichenfläche.malfläche) + { + zeichenfläche.alleSymbole.remove(this); + zeichenfläche.malfläche.repaint(); + } + } + + /** + * Bringt das Objekt eine Ebene nach vorn. + */ + void NachVornBringen () + { + synchronized (zeichenfläche.malfläche) + { + int index = zeichenfläche.alleSymbole.indexOf(this); + if (index < zeichenfläche.alleSymbole.size() - 1) + { + zeichenfläche.alleSymbole.set(index, zeichenfläche.alleSymbole.get(index + 1)); + zeichenfläche.alleSymbole.set(index + 1, this); + zeichenfläche.malfläche.repaint(); + } + } + } + + /** + * Bringt das Objekt in die vorderste Ebene. + */ + void GanzNachVornBringen () + { + synchronized (zeichenfläche.malfläche) + { + int index = zeichenfläche.alleSymbole.indexOf(this); + if (index < zeichenfläche.alleSymbole.size() - 1) + { + zeichenfläche.alleSymbole.remove(index); + zeichenfläche.alleSymbole.add(this); + zeichenfläche.malfläche.repaint(); + } + } + } + + /** + * Bringt das Objekt eine Ebene nach hinten. + */ + void NachHintenBringen () + { + synchronized (zeichenfläche.malfläche) + { + int index = zeichenfläche.alleSymbole.indexOf(this); + if (index > 0) + { + zeichenfläche.alleSymbole.set(index, zeichenfläche.alleSymbole.get(index - 1)); + zeichenfläche.alleSymbole.set(index - 1, this); + zeichenfläche.malfläche.repaint(); + } + } + } + + /** + * Bringt das Objekt in die hinterste Ebene. + */ + void GanzNachHintenBringen () + { + synchronized (zeichenfläche.malfläche) + { + int index = zeichenfläche.alleSymbole.indexOf(this); + if (index > 0) + { + zeichenfläche.alleSymbole.remove(index); + zeichenfläche.alleSymbole.add(0, this); + zeichenfläche.malfläche.repaint(); + } + } + } + + /** + * Testet, ob der angegebene Punkt innerhalb der Figur ist. + * @param x x-Koordinate des zu testenden Punktes + * @param y y-Koordinate des zu testenden Punktes + * @return wahr, wenn der Punkt innerhalb der Figur ist + */ + boolean IstInnerhalb (int x, int y) + { + return form.contains(x, y); + } + + /** + * Testet, ob die beiden Figuren überlappen. + * @param wen die andere Form + * @return wahr, wenn die beiden Formen überlappen. + */ + boolean Schneidet (Area wen) + { + Area area = new Area(form); + area.intersect (wen); + return !area.isEmpty(); + } + + /** + * Zeichnet das Objekt + * @param g das Grafikobjekt zum Zeichnen + */ + void Zeichnen(Graphics g) + { + g.setColor(c); + ((Graphics2D) g).fill(form); + } + + /** + * Berechnet den Drehwinkel gemäß den Konventionen des Graphik-Frameworks. + * Für Java: Winkel in Radians, positive Drehrichtng im Uhrzeiger. + * @param winkel: Der Winkel in Grad, mathematischer Drehsinn + * @return Winkel für Graphik-Framework + */ + double DrehwinkelGeben (int winkel) + { + return - Math.PI * winkel / 180.0; + } + + /** + * Erstellt die Form des Objekts. + */ + abstract void FormErzeugen(); + } + + /** + * Objekte dieser Klasse verwalten ein Rechteck. + */ + private class RechteckIntern extends GrafikSymbol + { + /** + * Erstellt die Form des Rechtecks. + */ + @Override void FormErzeugen() + { + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (winkel), this.x + b / 2, this.y + h / 2); + form = new Area(new Path2D.Double (new Rectangle2D.Double(this.x, this.y, b, h), a)); + } + } + + /** + * Objekte dieser Klasse verwalten eine Ellipse. + */ + private class EllipseIntern extends GrafikSymbol + { + /** + * Erstellt die Form der Ellipse. + */ + @Override void FormErzeugen() + { + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (winkel), this.x + b / 2, this.y + h / 2); + form = new Area(new Path2D.Double (new Ellipse2D.Double(this.x, this.y, b, h), a)); + } + } + + /** + * Objekte dieser Klasse verwalten ein Dreieck. + */ + private class DreieckIntern extends GrafikSymbol + { + /** + * Erstellt die Form des Dreiecks. + */ + @Override void FormErzeugen() + { + Polygon rand = new Polygon (new int [] {x + b / 2, x + b, x, x + b / 2}, + new int [] {y, y + h, y + h, y}, 4); + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (winkel), this.x + b / 2, this.y + h / 2); + form = new Area(new Path2D.Double (rand, a)); + } + } + + /** + * Objekte dieser Klasse verwalten einen Text. + */ + class TextIntern extends GrafikSymbol + { + /** Der aktuelle Text. */ + private String text; + /** Die aktuelle Textgröße. */ + float size; + + /** + * Belegt text und size mit Defaultwerten. + */ + TextIntern () + { + super(); + text = "Text"; + size = 12; + c = Color.black; + } + + /** + * Erstellt die Form des Textes. + * Dummy, legt ein leeres Area an. + */ + @Override void FormErzeugen() + { + form = new Area(); + } + + /** + * Testet, ob der angegebene Punkt innerhalb der Figur ist. + * @param x x-Koordinate des zu testenden Punktes + * @param y y-Koordinate des zu testenden Punktes + * @return falsch + */ + @Override boolean IstInnerhalb (int x, int y) + { + return false; + } + + /** + * Setzt den aktuellen Text. + * @param t der neue Text + */ + void TextSetzen (String t) + { + text = t; + zeichenfläche.malfläche.repaint(); + } + + /** + * Setzt die Größe des Textes. + */ + void TextGrößeSetzen (int größe) + { + size = größe; + zeichenfläche.malfläche.repaint(); + } + + /** + * Vergrößert den Text. + */ + void TextVergrößern() + { + if (size <= 10) + { + size += 1; + } + else if (size <= 40) + { + size += 2; + } + else + { + size += 4; + } + zeichenfläche.malfläche.repaint(); + } + + /** + * Verkleinert den Text. + */ + void TextVerkleinern() + { + if (size <= 10) + { + size -= 1; + } + else if (size <= 40) + { + size -= 2; + } + else + { + size -= 4; + } + if (size < 1) + { + size = 1; + } + zeichenfläche.malfläche.repaint(); + } + + /** + * Zeichnet das Objekt als Dreieck in der gegebenen Farbe. + * @param g das Grafikobjekt zum Zeichnen + */ + @Override void Zeichnen(Graphics g) + { + g.setColor(c); + Font f = g.getFont(); + Font f2 = f.deriveFont(size); + g.setFont(f2); + + if (winkel == 0) + { + g.drawString(text, x, y); + } + else + { + Graphics2D g2 = (Graphics2D) g; + AffineTransform alt = g2.getTransform(); + //g2.rotate(DrehwinkelGeben (winkel), x + b / 2, y + h / 2); + //g2.rotate(DrehwinkelGeben (winkel), x + text.length() * size / 4, y + size / 2); + Rectangle2D bounds = f2.getStringBounds(text, g2.getFontRenderContext()); + g2.rotate(DrehwinkelGeben (winkel), x + bounds.getWidth() / 2, y - bounds.getHeight() / 2); + g.drawString(text, x, y); + g2.setTransform(alt); + } + g.setFont(f); + } + } + + /** + * Oberklasse für alle Elemente einer Figur (Figur, Turtle). + */ + private abstract class FigurenElement + { + double xe; + double ye; + double breite; + double höhe; + Color c; + /** + * Zeichnet das Figurenelement. + * @param g das Grafikobjekt + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + abstract void ElementZeichnen(Graphics2D g, double größe, int x, int y); + + /** + * Fügt den Pfadteil deiser Komponente zum umgebenden Pfad hinzu. + * @param p der Gesamtpfad + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + abstract void ElementZuForm (Path2D.Double p, double größe, int x, int y); + } + + /** + * Ein rechteckiges Figurenelement. + */ + private class FigurenElementRechteck extends FigurenElement + { + /** + * Der Konstruktor speichert die Rahmendaten. + * @param x x-Koordinate der linken oberen Ecke des Rechtecks relativ zum Aufhängepunkt. + * @param y y-Koordinate der linken oberen Ecke des Rechtecks relativ zum Aufhängepunkt. + * @param breite Breite des Rechtecks + * @param höhe Höhe des Rechtecks + * @param c Farbe des Rechtecks + */ + FigurenElementRechteck (double x, double y, double breite, double höhe, Color c) + { + this.xe = x; + this.ye = y; + this.breite = breite; + this.höhe = höhe; + this.c = c; + } + + /** + * Zeichnet das Figurenelement. + * @param g das Grafikobjekt + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + @Override void ElementZeichnen(Graphics2D g, double größe, int x, int y) + { + g.setColor(c); + g.fill(new Rectangle2D.Double (x+größe*xe/100.0, y+größe*ye/100.0, größe*breite/100.0, größe*höhe/100.0)); + } + + /** + * Fügt den Pfadteil dieser Komponente zum umgebenden Pfad hinzu. + * @param p der Gesamtpfad + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + @Override void ElementZuForm (Path2D.Double p, double größe, int x, int y) + { + p.append(new Rectangle2D.Double (x+größe*xe/100.0, y+größe*ye/100.0, größe*breite/100.0, größe*höhe/100.0), false); + } + } + + /** + * Ein elliptisches Figurenelement. + */ + private class FigurenElementEllipse extends FigurenElement + { + /** + * Der Konstruktor speichert die Rahmendaten. + * @param x x-Koordinate der linken oberen Ecke des umgebenden Rechtecks relativ zum Aufhängepunkt. + * @param y y-Koordinate der linken oberen Ecke des umgebenden Rechtecks relativ zum Aufhängepunkt. + * @param breite Breite der Ellipse + * @param höhe Höhe der Ellipse + * @param c Farbe der Ellipse + */ + FigurenElementEllipse (double x, double y, double breite, double höhe, Color c) + { + this.xe = x; + this.ye = y; + this.breite = breite; + this.höhe = höhe; + this.c = c; + } + + /** + * Zeichnet das Figurenelement. + * @param g das Grafikobjekt + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + @Override void ElementZeichnen(Graphics2D g, double größe, int x, int y) + { + g.setColor(c); + g.fill(new Ellipse2D.Double (x+größe*xe/100.0, y+größe*ye/100.0, größe*breite/100.0, größe*höhe/100.0)); + } + + /** + * Fügt den Pfadteil dieser Komponente zum umgebenden Pfad hinzu. + * @param p der Gesamtpfad + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + @Override void ElementZuForm (Path2D.Double p, double größe, int x, int y) + { + p.append(new Ellipse2D.Double (x+größe*xe/100.0, y+größe*ye/100.0, größe*breite/100.0, größe*höhe/100.0), false); + } + } + + /** + * Ein Figurenelement begrenzt durch das angegebene Polygon. + */ + private class FigurenElementPolygon extends FigurenElement + { + /** Das Polygonobjekt */ + private Polygon poly; + + /** + * Der Konstruktor speichert die Rahmendaten. + * @param x x-Koordinaten der Stützpunkte des Polygons relativ zum Aufhängepunkt. + * @param y y-Koordinaten der Stützpunkte des Polygons relativ zum Aufhängepunkt. + * @param c Farbe der Polygonfläche + */ + FigurenElementPolygon (int [] x, int[] y, Color c) + { + int anz = x.length <= y.length ? x.length : y.length; + poly = new Polygon (x, y, anz); + Rectangle2D bounds = poly.getBounds2D(); + xe = bounds.getX(); + ye = bounds.getY(); + breite = bounds.getWidth(); + höhe = bounds.getHeight(); + this.c = c; + } + + /** + * Zeichnet das Figurenelement. + * @param g das Grafikobjekt + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + @Override void ElementZeichnen(Graphics2D g, double größe, int x, int y) + { + g.setColor(c); + AffineTransform at = new AffineTransform(größe/100.0, 0, 0, größe/100.0, x, y); + g.fill(new Path2D.Double (poly, at)); + } + + /** + * Fügt den Pfadteil dieser Komponente zum umgebenden Pfad hinzu. + * @param p der Gesamtpfad + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + @Override void ElementZuForm (Path2D.Double p, double größe, int x, int y) + { + AffineTransform at = new AffineTransform(größe/100.0, 0, 0, größe/100.0, x, y); + Path2D.Double p2 = new Path2D.Double (poly, at); + p2.closePath(); + p2.setWindingRule(Path2D.WIND_EVEN_ODD); + p.append(p2, false); + } + } + + /** + * Das Objekt dieser Klasse zeichnet den Weg der Turtle. + */ + class TurtleIntern extends GrafikSymbol + { + private class LinienElement + { + /** x-Koordinate des Startpunktes. */ + private double xStart; + /** y-Koordinate des Startpunktes. */ + private double yStart; + /** x-Koordinate des Endpunktes. */ + private double xEnde; + /** y-Koordinate des Endpunktes. */ + private double yEnde; + /** Farbe des LinienElements. */ + private Color c; + + LinienElement (double xStart, double yStart, double xEnde, double yEnde, Color c) + { + this.xStart = xStart; + this.yStart = yStart; + this.xEnde = xEnde; + this.yEnde = yEnde; + this.c = c; + } + + void Zeichnen (Graphics2D g) + { + g.setColor(c); + g.draw(new Line2D.Double (xStart, yStart, xEnde, yEnde)); + } + } + + /** + * Verwaltet das Hintergrundfenster für die Turtlezeichnung. + */ + private class HintergrundBild + { + /** Das aktuelle Hintergrundbild. */ + private BufferedImage bild; + /** Das zugehörige Zeichenobjekt. */ + private Graphics2D g; + + /** + * Der Konstruktor legt das Bild in der Größe der Zeichenfläche an. + */ + HintergrundBild() + { + bild = new BufferedImage(Zeichenfenster.MalflächenBreiteGeben(), Zeichenfenster.MalflächenBreiteGeben(), BufferedImage.TYPE_INT_ARGB); + g = bild.createGraphics(); + g.setColor(new Color (0, 0, 0, 0)); + g.fillRect(0, 0, bild.getWidth(), bild.getHeight()); + } + + /** + * Zeichent die angegebe Linie in das Bild. + * @param linie das zu zeichnende Linienelement. + */ + void LinieZeichnen(LinienElement linie) + { + linie.Zeichnen(g); + } + + /** + * Zeichnet das Bild in das angegebene Zeichenobjekt. + * @param wohin Zeichenobjekt + */ + void BildZeichnen (Graphics2D wohin) + { + wohin.drawImage(bild, null, 0, 0); + } + } + + /** Genaue x-Koordinate der Turtle. */ + double xD; + /** Genaue y-Koordinate der Turtle. */ + double yD; + /** Startkoordinate der Turtle. */ + private int homeX; + /** Startkoordinate der Turtle. */ + private int homeY; + /** Startwinkel der Turtle. */ + private int homeWinkel; + /** Stiftposition. */ + boolean stiftUnten; + /** Die Sichtbarkeit des Turtle-Symbols. */ + private boolean symbolSichtbar; + /** Linienelemente. */ + private ArrayList linien; + /** Standardfigur für Turtle. */ + private LinkedList standardFigur; + /** Das Hintergrundbild für die Linien. */ + private HintergrundBild hintergrund; + + /** + * Legt die Turtle mit Startpunkt (100|200) in Richtung 0˚ an. + */ + TurtleIntern () + { + super (); + x = 100; + y = 200; + xD = x; + yD = y; + h = 40; + b = 40; + homeX=x; + homeY=y; + homeWinkel=winkel; + c = Color.black; + stiftUnten = true; + symbolSichtbar = true; + linien = new ArrayList(); + hintergrund = new HintergrundBild(); + standardFigur = new LinkedList(); + StandardfigurErzeugen(); + FormErzeugen(); + } + + /** + * Baut die Standardfigur aus den Elementen auf. + */ + private void StandardfigurErzeugen() + { + //Kopf + standardFigur.add(new FigurenElementEllipse(50, -12.5, 25, 25, Color.GREEN)); + //Beine + standardFigur.add(new FigurenElementEllipse(22.5, -32.5, 12.5, 17.5, Color.GREEN)); + standardFigur.add(new FigurenElementEllipse(40.0, -32.5, 12.5, 17.5, Color.GREEN)); + standardFigur.add(new FigurenElementEllipse(22.5, 15.0, 12.5, 17.5, Color.GREEN)); + standardFigur.add(new FigurenElementEllipse(40.0, 15.0, 12.5, 17.5, Color.GREEN)); + //Augen + standardFigur.add(new FigurenElementRechteck(67.5, -10.0, 5.0, 7.5, c)); + standardFigur.add(new FigurenElementRechteck(67.5, 2.5, 5.0, 7.5, c)); + //Schwanz + standardFigur.add(new FigurenElementEllipse(0, -3.75, 25, 7.5, c)); + //Rumpf + standardFigur.add(new FigurenElementEllipse(7.5, -23.75, 57.5, 47.5, braun)); + } + + /** + * Passt das Hintergrundbild an eine neue Größe der Zeichenfläche an. + */ + void NeueGrößeSetzen() + { + hintergrund = new HintergrundBild(); + for (LinienElement l: linien) + { + hintergrund.LinieZeichnen(l); + } + } + + /** + * Erstellt die Form der Turtle. + */ + @Override void FormErzeugen() + { + Area area = new Area(); + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (winkel), this.x, this.y); + double größe = h > b ? b : h; + if (standardFigur != null) + { + synchronized (standardFigur) + { + for (FigurenElement e: standardFigur) + { + Path2D.Double p = new Path2D.Double(); + e.ElementZuForm(p, größe, x, y); + area.add( new Area(new Path2D.Double (p, a))); + } + } + + } + form = area; + } + + /** + * Setzt die Position (der linken oberen Ecke) des Objekts. + * @param x x-Position der linken oberen Ecke + * @param y y-Position der linken oberen Ecke + */ + @Override void PositionSetzen (int x, int y) + { + super.PositionSetzen (x, y); + xD = x; + yD = y; + } + + /** + * Setzt die Turtle wieder an ihre Ausgangsposition. + */ + void ZumStartpunktGehen() + { + x = homeX; + y = homeY; + xD = x; + yD = y; + winkel = homeWinkel; + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Bewegt die Turtle nach vorne. + * @param länge Anzahl der Längeneinheiten + */ + void Gehen(double länge) + { + double neuX = xD + Math.cos(DrehwinkelGeben (winkel)) * länge; + double neuY = yD + Math.sin(DrehwinkelGeben (winkel)) * länge; + if (stiftUnten) + { + synchronized (this) + { + LinienElement l = new LinienElement(xD, yD, neuX, neuY, c); + linien.add (l); + hintergrund.LinieZeichnen (l); + } + } + xD = neuX; + yD = neuY; + x =(int) Math.round(xD); + y =(int) Math.round(yD); + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Dreht die Turtle + * @param grad Drehwinkel im Gradmass + */ + void Drehen(int grad) + { + winkel = WinkelNormieren(winkel + grad); + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Versetzt Zeichenfläche und Turtle in den Ausgangszustand + */ + void Löschen() + { + linien.clear(); + hintergrund = new HintergrundBild(); + ZumStartpunktGehen(); + } + + /** + * Turtle wechselt in den Modus "nicht zeichnen" + */ + void StiftHeben() + { + stiftUnten = false; + } + + /** + * Turtle wechselt in den Modus "zeichnen" + */ + void StiftSenken() + { + stiftUnten = true; + } + + /** + * Schaltet die Sichtbarkeit des Turtlesymbols ein oder aus. + * Erlaubte Parameterwerte: true, false + * @param sichtbar (neue) Sichtbarkeit des Turtlesymbols + */ + void SichtbarkeitFürSymbolSetzen (boolean sichtbar) + { + symbolSichtbar = sichtbar; + zeichenfläche.malfläche.repaint(); + } + + /** + * Testet, ob der angegebene Punkt innerhalb der Figur ist. + * @param x x-Koordinate des zu testenden Punktes + * @param y y-Koordinate des zu testenden Punktes + * @return wahr, wenn der Punkt innerhalb der Figur ist + */ + + /** + * Testet, ob die Turtle eine (sichtbare) Figur berührt. + * @return true, wenn die Turtlekoordinaten innerhalb einer Grafikfigur sind + */ + boolean Berührt () + { + for (GrafikSymbol g: zeichenfläche.alleSymbole) + { + if ((g != this) && g.IstInnerhalb(x, y) && g.sichtbar && (!(g instanceof TurtleIntern) || ((TurtleIntern) g).symbolSichtbar)) + { + return true; + } + } + return false; + } + + /** + * Testet, ob die Turtle eine (sichtbare) Figur in der angegebenen Farbe berührt. + * Bei Überlappungen + * @param farbe die Farbe, die die berührte Figur haben muss. + * @return true, wenn die Turtlekoordinaten innerhalb einer Grafikfigur in der angegebenen Farbe sind + */ + boolean Berührt (String farbe) + { + Color c2 = FarbeCodieren(farbe); + boolean ok = false; + for (GrafikSymbol g: zeichenfläche.alleSymbole) + { + if ((g != this) && g.IstInnerhalb(x, y) && g.sichtbar) + { + if (g instanceof TurtleIntern) + { + TurtleIntern t = (TurtleIntern) g; + if (t.symbolSichtbar) + { + for (FigurenElement e: t.standardFigur) + { + Path2D.Double p = new Path2D.Double(); + double größe = t.h > t.b ? t.b : t.h; + e.ElementZuForm(p, größe, t.x, t.y); + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (t.winkel), t.x, t.y); + p = new Path2D.Double (p, a); + if (p.contains(x, y)) + { + ok = c2.equals(e.c); + } + } + } + } + else if (g instanceof FigurIntern) + { + FigurIntern t = (FigurIntern) g; + LinkedList figur = ((t.eigeneFigur == null) || (t.eigeneFigur.size() == 0)) ? t.standardFigur : t.eigeneFigur; + for (FigurenElement e: figur) + { + Path2D.Double p = new Path2D.Double(); + double größe = t.h > t.b ? t.b : t.h; + e.ElementZuForm(p, größe, t.x, t.y); + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (t.winkel), t.x, t.y); + p = new Path2D.Double (p, a); + if (p.contains(x, y)) + { + ok = c2.equals(e.c); + } + } + } + else + { + ok = ok || c2.equals(g.c); + } + } + } + return ok; + } + + /** + * Testet, ob die Turtle die (sichtbare, ) angegebene Figur berührt. + * @param object das Objekt, das getestet werden soll. + * @return true, wenn die Turtlekoordinaten innerhalb einer Grafikfigur in der angegebenen Farbe sind + */ + boolean Berührt (Object object) + { + GrafikSymbol s = null; + if (object instanceof Rechteck) + { + s = ((Rechteck) object).symbol; + } + else if (object instanceof Dreieck) + { + s = ((Dreieck) object).symbol; + } + else if (object instanceof Kreis) + { + s = ((Kreis) object).symbol; + } + else if (object instanceof Turtle) + { + s = ((Turtle) object).symbol; + } + else if (object instanceof Figur) + { + s = ((Figur) object).symbol; + } + return (s != null) && (s != this) && s.IstInnerhalb(x, y) && s.sichtbar && (!(s instanceof TurtleIntern) || ((TurtleIntern) s).symbolSichtbar); + } + + /** + * Zeichnet das Objekt als Dreieck in der gegebenen Farbe. + * @param g das Grafikobjekt zum Zeichnen + */ + @Override void Zeichnen(Graphics g) + { + Graphics2D g2 = (Graphics2D) g; + synchronized (this) + { + hintergrund.BildZeichnen(g2); + } + + if (symbolSichtbar) + { + g.setColor(Color.black); + double größe = h > b ? b : h; + AffineTransform alt = g2.getTransform(); + g2.rotate(DrehwinkelGeben (winkel), x, y); + if (standardFigur != null) + { + synchronized (standardFigur) + { + for (FigurenElement e: standardFigur) + { + e.ElementZeichnen(g2, größe, x, y); + } + } + } + g2.setTransform(alt); + } + } + } + + /** + * Das Objekt dieser Klasse ist ein in der Gestalt definierbarer Akteur. + */ + class FigurIntern extends GrafikSymbol + { + + /** Genaue x-Koordinate der Figur. */ + double xD; + /** Genaue y-Koordinate der Figur. */ + double yD; + /** Startkoordinate der Figur. */ + private int homeX; + /** Startkoordinate der Figur. */ + private int homeY; + /** Startwinkel der Figur. */ + private int homeWinkel; + /** Eigene Figur für Figur. */ + private LinkedList eigeneFigur; + /** Standardfigur für Figur. */ + private LinkedList standardFigur; + + /** + * Legt die Figur mit Startpunkt (100|200) in Richtung 0˚ an. + */ + FigurIntern () + { + super (); + x = 100; + y = 200; + xD = x; + yD = y; + h = 40; + b = 40; + homeX=x; + homeY=y; + homeWinkel=winkel; + c = Color.black; + eigeneFigur = new LinkedList(); + standardFigur = new LinkedList(); + StandardfigurErzeugen(); + FormErzeugen(); + } + + /** + * Baut die Standardfigur aus den Elementen auf. + */ + private void StandardfigurErzeugen() + { + int[] x = new int [] {-50, 50, -50}; + int[] y = new int [] {-50, 0, 50}; + standardFigur.add (new FigurenElementPolygon (x, y, Color.yellow)); + standardFigur.add(new FigurenElementEllipse(-10, -10, 20, 20, Color.blue)); + } + + /** + * Erstellt die Form der Figur. + */ + @Override void FormErzeugen() + { + Area area = new Area(); + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (winkel), this.x, this.y); + double größe = h > b ? b : h; + if (standardFigur != null) + { + LinkedList figur = ((eigeneFigur == null) || (eigeneFigur.size() == 0)) ? standardFigur : eigeneFigur; + synchronized (figur) + { + for (FigurenElement e: figur) + { + Path2D.Double p = new Path2D.Double(); + e.ElementZuForm(p, größe, x, y); + area.add(new Area(new Path2D.Double (p, a))); + } + } + + } + form = area; + } + + /** + * Setzt die Position (der Mitte) des Objekts. + * @param x x-Position der Mitte + * @param y y-Position der Mitte + */ + @Override void PositionSetzen (int x, int y) + { + super.PositionSetzen (x, y); + xD = x; + yD = y; + } + + /** + * Setzt die Figur wieder an ihre Ausgangsposition. + */ + void ZumStartpunktGehen() + { + x = homeX; + y = homeY; + xD = x; + yD = y; + winkel = homeWinkel; + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Bewegt die Figur nach vorne. + * @param länge Anzahl der Längeneinheiten + */ + void Gehen(double länge) + { + double neuX = xD + Math.cos(DrehwinkelGeben (winkel)) * länge; + double neuY = yD + Math.sin(DrehwinkelGeben (winkel)) * länge; + xD = neuX; + yD = neuY; + x =(int) Math.round(xD); + y =(int) Math.round(yD); + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Dreht die Figur + * @param grad Drehwinkel im Gradmass + */ + void Drehen(int grad) + { + winkel = WinkelNormieren(winkel + grad); + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Testet, ob die Figur eine (sichtbare) Grafik-Figur berührt. + * @return true, wenn die Figurkoordinaten innerhalb einer Grafikfigur sind + */ + boolean Berührt () + { + for (GrafikSymbol g: zeichenfläche.alleSymbole) + { + if ((g != this) && g.Schneidet(form) && g.sichtbar && (!(g instanceof TurtleIntern) || ((TurtleIntern) g).symbolSichtbar)) + { + return true; + } + } + return false; + } + + /** + * Testet, ob die Figur eine (sichtbare) Grafik-Figur in der angegebenen Farbe berührt. + * Bei Überlappungen + * @param farbe die Farbe, die die berührte Figur haben muss. + * @return true, wenn die Figurkoordinaten innerhalb einer Grafikfigur in der angegebenen Farbe sind + */ + boolean Berührt (String farbe) + { + Color c2 = FarbeCodieren(farbe); + boolean ok = false; + for (GrafikSymbol g: zeichenfläche.alleSymbole) + { + if ((g != this) && g.Schneidet(form) && g.sichtbar) + { + if (g instanceof TurtleIntern) + { + TurtleIntern t = (TurtleIntern) g; + if (t.symbolSichtbar) + { + Area[] areas = new Area [t.standardFigur.size()]; + Color[] colors = new Color [t.standardFigur.size()]; + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (t.winkel), t.x, t.y); + int pos = 0; + for (FigurenElement e: t.standardFigur) + { + Path2D.Double p = new Path2D.Double(); + double größe = t.h > t.b ? t.b : t.h; + e.ElementZuForm(p, größe, t.x, t.y); + p = new Path2D.Double (p, a); + areas [pos] = new Area(p); + colors[pos] = e.c; + for (int i = pos - 1; i >= 0;i--) + { + areas[i].subtract(areas[pos]); + } + pos += 1; + } + for (int i = 0; i < areas.length; i++) + { + if (Schneidet(areas[i]) && (c2.equals(colors[i]))) + { + ok = true; + } + } + } + } + else if (g instanceof FigurIntern) + { + FigurIntern t = (FigurIntern) g; + LinkedList figur = ((t.eigeneFigur == null) || (t.eigeneFigur.size() == 0)) ? t.standardFigur : t.eigeneFigur; + Area[] areas = new Area [figur.size()]; + Color[] colors = new Color [figur.size()]; + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (t.winkel), t.x, t.y); + int pos = 0; + for (FigurenElement e: figur) + { + Path2D.Double p = new Path2D.Double(); + double größe = t.h > t.b ? t.b : t.h; + e.ElementZuForm(p, größe, t.x, t.y); + p = new Path2D.Double (p, a); + areas [pos] = new Area(p); + colors[pos] = e.c; + for (int i = pos - 1; i >= 0;i--) + { + areas[i].subtract(areas[pos]); + } + pos += 1; + } + for (int i = 0; i < areas.length; i++) + { + if (Schneidet(areas[i]) && (c2.equals(colors[i]))) + { + ok = true; + } + } + } + else + { + ok = ok || c2.equals(g.c); + } + } + } + return ok; + } + + /** + * Testet, ob die Figur die (sichtbare, ) angegebene Grafik-Figur berührt. + * @param object das Objekt, das getestet werden soll. + * @return true, wenn die Turtlekoordinaten innerhalb einer Grafikfigur in der angegebenen Farbe sind + */ + boolean Berührt (Object object) + { + GrafikSymbol s = null; + if (object instanceof Rechteck) + { + s = ((Rechteck) object).symbol; + } + else if (object instanceof Dreieck) + { + s = ((Dreieck) object).symbol; + } + else if (object instanceof Kreis) + { + s = ((Kreis) object).symbol; + } + else if (object instanceof Turtle) + { + s = ((Turtle) object).symbol; + } + else if (object instanceof Figur) + { + s = ((Figur) object).symbol; + } + return (s != null) && (s != this) && s.Schneidet(form) && s.sichtbar && (!(s instanceof TurtleIntern) || ((TurtleIntern) s).symbolSichtbar); + } + + /** + * Erzeugt ein neues, rechteckiges Element einer eigenen Darstellung der Figur. + * Alle Werte beziehen sich auf eine Figur der Größe 100 und den Koordinaten (0|0) in der Mitte des Quadrats + * @param x x-Wert der linken oberen Ecke des Rechtecks + * @param y y-Wert der linken oberen Ecke des Rechtecks + * @param breite Breite des Rechtecks + * @param höhe Höhe des Rechtecks + * @param farbe (Füll)Farbe des Rechtecks + */ + void FigurteilFestlegenRechteck (int x, int y, int breite, int höhe, String farbe) + { + synchronized (eigeneFigur) + { + eigeneFigur.add(new FigurenElementRechteck(x, y, breite, höhe, FarbeCodieren(farbe))); + } + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Erzeugt ein neues, elliptisches Element einer eigenen Darstellung der Figur. + * Alle Werte beziehen sich auf eine Figur der Größe 100 und den Koordinaten (0|0) in der Mitte des Quadrats + * @param x x-Wert der linken oberen Ecke des umgebenden Rechtecks der Ellipse + * @param y y-Wert der linken oberen Ecke des umgebenden Rechtecks der Ellipse + * @param breite Breite des umgebenden Rechtecks der Ellipse + * @param höhe Höhe des umgebenden Rechtecks der Ellipse + * @param farbe (Füll)Farbe der Ellipse + */ + void FigurteilFestlegenEllipse (int x, int y, int breite, int höhe, String farbe) + { + synchronized (eigeneFigur) + { + eigeneFigur.add(new FigurenElementEllipse(x, y, breite, höhe, FarbeCodieren(farbe))); + } + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Erzeugt ein neues, dreieckiges Element einer eigenen Darstellung der Figur. + * Alle Werte beziehen sich auf eine Figur der Größe 100 und den Koordinaten (0|0) in der Mitte des Quadrats + * @param x1 x-Wert des ersten Punkts des Dreiecks + * @param y1 y-Wert des ersten Punkts des Dreiecks + * @param x2 x-Wert des zweiten Punkts des Dreiecks + * @param y2 y-Wert des zweiten Punkts des Dreiecks + * @param x3 x-Wert des dritten Punkts des Dreiecks + * @param y3 y-Wert des dritten Punkts des Dreiecks + * @param farbe (Füll)Farbe der Ellipse + */ + void FigurteilFestlegenDreieck (int x1, int y1, int x2, int y2, int x3, int y3, String farbe) + { + synchronized (eigeneFigur) + { + int[] x = new int [] {x1, x2, x3}; + int[] y = new int [] {y1, y2, y3}; + eigeneFigur.add(new FigurenElementPolygon(x, y, FarbeCodieren(farbe))); + } + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Löscht die Vereinbarung für die eigene Darstellung Figur. + * Die Figur wird wieder durch die Originalfigur dargestellt. + */ + void EigeneFigurLöschen() + { + eigeneFigur.clear(); + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Zeichnet das Objekt als Dreieck in der gegebenen Farbe. + * @param g das Grafikobjekt zum Zeichnen + */ + @Override void Zeichnen(Graphics g) + { + Graphics2D g2 = (Graphics2D) g; + // Outline + g.setColor(Color.black); + Stroke stAlt = g2.getStroke(); + g2.setStroke(new BasicStroke(3.0f)); + g2.draw(form); + g2.setStroke(stAlt); + // Füllung + double größe = h > b ? b : h; + AffineTransform alt = g2.getTransform(); + g2.rotate(DrehwinkelGeben (winkel), x, y); + if (standardFigur != null) + { + LinkedList figur = ((eigeneFigur == null) || (eigeneFigur.size() == 0)) ? standardFigur : eigeneFigur; + synchronized (figur) + { + for (FigurenElement e: figur) + { + e.ElementZeichnen(g2, größe, x, y); + } + } + } + g2.setTransform(alt); + } + } +} diff --git a/package.bluej b/package.bluej new file mode 100644 index 0000000..da3ab8a --- /dev/null +++ b/package.bluej @@ -0,0 +1,170 @@ +#BlueJ package file +dependency1.from=Turtle +dependency1.to=Zeichenfenster +dependency1.type=UsesDependency +dependency10.from=Aufbau +dependency10.to=DreieckBesser +dependency10.type=UsesDependency +dependency11.from=Aufbau +dependency11.to=RechteckBesser +dependency11.type=UsesDependency +dependency12.from=Ereignisbehandlung +dependency12.to=Zeichenfenster +dependency12.type=UsesDependency +dependency13.from=Zeichenfenster +dependency13.to=Rechteck +dependency13.type=UsesDependency +dependency14.from=Zeichenfenster +dependency14.to=Dreieck +dependency14.type=UsesDependency +dependency15.from=Zeichenfenster +dependency15.to=Kreis +dependency15.type=UsesDependency +dependency16.from=Zeichenfenster +dependency16.to=Turtle +dependency16.type=UsesDependency +dependency17.from=Zeichenfenster +dependency17.to=Figur +dependency17.type=UsesDependency +dependency18.from=Kreis +dependency18.to=Zeichenfenster +dependency18.type=UsesDependency +dependency2.from=Rechteck +dependency2.to=Zeichenfenster +dependency2.type=UsesDependency +dependency3.from=Aufbau2 +dependency3.to=RechteckBesser +dependency3.type=UsesDependency +dependency4.from=Aufbau2 +dependency4.to=DreieckBesser +dependency4.type=UsesDependency +dependency5.from=Aufbau2 +dependency5.to=KreisBesser +dependency5.type=UsesDependency +dependency6.from=Figur +dependency6.to=Zeichenfenster +dependency6.type=UsesDependency +dependency7.from=Text +dependency7.to=Zeichenfenster +dependency7.type=UsesDependency +dependency8.from=Dreieck +dependency8.to=Zeichenfenster +dependency8.type=UsesDependency +dependency9.from=Aufbau +dependency9.to=KreisBesser +dependency9.type=UsesDependency +editor.fx.0.height=0 +editor.fx.0.width=0 +editor.fx.0.x=0 +editor.fx.0.y=0 +objectbench.height=174 +objectbench.width=1256 +package.divider.horizontal=0.5998578535891969 +package.divider.vertical=0.6901248581157774 +package.editor.height=397 +package.editor.width=1132 +package.editor.x=0 +package.editor.y=0 +package.frame.height=686 +package.frame.width=1294 +package.numDependencies=18 +package.numTargets=13 +package.showExtends=true +package.showUses=true +project.charset=UTF-8 +readme.height=60 +readme.name=@README +readme.width=48 +readme.x=10 +readme.y=10 +target1.height=50 +target1.name=Turtle +target1.showInterface=false +target1.type=ClassTarget +target1.width=80 +target1.x=510 +target1.y=100 +target10.height=50 +target10.name=KreisBesser +target10.showInterface=false +target10.type=ClassTarget +target10.width=90 +target10.x=430 +target10.y=210 +target11.height=50 +target11.name=Zeichenfenster +target11.showInterface=false +target11.type=ClassTarget +target11.width=120 +target11.x=70 +target11.y=20 +target12.height=50 +target12.name=DreieckBesser +target12.showInterface=false +target12.type=ClassTarget +target12.width=110 +target12.x=290 +target12.y=240 +target13.height=50 +target13.name=Kreis +target13.showInterface=false +target13.type=ClassTarget +target13.width=80 +target13.x=400 +target13.y=120 +target2.height=50 +target2.name=Rechteck +target2.showInterface=false +target2.type=ClassTarget +target2.width=80 +target2.x=190 +target2.y=160 +target3.height=50 +target3.name=Aufbau2 +target3.showInterface=false +target3.type=ClassTarget +target3.width=80 +target3.x=780 +target3.y=310 +target4.height=50 +target4.name=Figur +target4.showInterface=false +target4.type=ClassTarget +target4.width=80 +target4.x=620 +target4.y=80 +target5.height=50 +target5.name=Text +target5.showInterface=false +target5.type=ClassTarget +target5.width=80 +target5.x=720 +target5.y=60 +target6.height=50 +target6.name=Dreieck +target6.showInterface=false +target6.type=ClassTarget +target6.width=80 +target6.x=290 +target6.y=140 +target7.height=50 +target7.name=Aufbau +target7.showInterface=false +target7.type=ClassTarget +target7.width=80 +target7.x=610 +target7.y=330 +target8.height=50 +target8.name=RechteckBesser +target8.showInterface=false +target8.type=ClassTarget +target8.width=120 +target8.x=140 +target8.y=270 +target9.height=50 +target9.name=Ereignisbehandlung +target9.showInterface=false +target9.type=ClassTarget +target9.width=150 +target9.x=820 +target9.y=40