Benutzer-Werkzeuge

Webseiten-Werkzeuge


klassen1:anwenden:start

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.


klassen1:anwenden:start [2024/08/31 12:03] (aktuell) – angelegt - Externe Bearbeitung 127.0.0.1
Zeile 1: Zeile 1:
 +{{ :klassen1:anwenden:pasted:20200828-185832.png?400}} 
 +====== Objekte erzeugen und verändern ======
 +Bevor wir eigene Klassen programmieren lernen wir, wie wir Objekte zu bereits bestehenden Klassen erzeugen können. Wir beginnen mit Grafikklassen wie ''Rectangle'' oder ''Circle'', weil man die grafische Repräsentation dieser Objekte gleich am Bildschirm sieht. 
 +
 +===== Objekte instanzieren ( = erzeugen) =====
 +Im folgenden Programm erzeugen wir zwei Circle-Objekte und ein Rectangle-Objekt. In Java verwendet man dazu den Operator ''new'' gefolgt vom Bezeichner der Klasse und - in Klammern - zusätzlichen Angaben (**Parametern**), die zum Erzeugen des Objekts benötigt werden.
 +<HTML>
 +<div style="clear: both; height: 0.5em;"></div>
 +</HTML>
 +
 +
 +
 +<HTML>
 +<div class="java-online" style="height: 200px; width: 100%;" data-java-online="{'withBottomPanel': false, 'id': 'Objekte1'}">
 +
 +<script type="text/plain" title="Objekte1.java">
 +new Circle(400, 200, 100);   // Kreis mit Mittelpunkt (400, 200) und Radius 100
 +new Circle(400, 400, 50);    // Kreis mit Mittelpunkt (400, 400) und Radius 50
 +
 +new Rectangle(50, 20, 100, 160);    // Rechteck; linke obere Ecke bei (50, 20); 
 +                                    // 100 breit, 160 hoch</script>
 +</div>
 +
 +</HTML>
 +
 +<WRAP center round info 60%>
 +Durch die Anweisung ''new Circle(400, 200, 100)'' wird ein neues Objekt der Klasse Circle (also ein Kreis-Objekt) **instanziert** ( = erzeugt ). Die Angaben in Klammern nennt man **Parameter**. Durch sie übermittlen wir dem Objekt die Informationen, die es zur Erzeugung braucht, im Falle eines ''Circle''-Objekts sind dies die Koordinaten des Mittelpunkts und der Radius. Beim Objekt der Klasse ''Rectangle'' sind die Parameter die Koordinaten der linken oberen Ecke, die Breite und die Höhe des Rechtecks. \\ \\ Zur Veranschaulichung siehst Du rechts oben eine Skizze des Zeichenbereichs. \\ \\ 
 +**Beachte:** Der Ursprung des Koordinatensystems liegt im Zeichenbereich **links oben**, die y-Achse zeigt nach **unten**! (Hier die [[https://gamedev.stackexchange.com/questions/83570/why-is-the-origin-in-computer-graphics-coordinates-at-the-top-left|Erklärung dafür]].) Falls nichts anderes angegeben wird, liegt der rechte Rand des Zeichenbereichs bei x = 800, der untere bei y = 600.
 +</WRAP>
 +
 +
 +<HTML>
 +<div style="clear: both"></div>
 +</HTML>
 +===== Methoden aufrufen =====
 +{{ :klassen1:anwenden:pasted:20200829-134255.png?400}}
 +Wir wollen die Füllfarbe eines Kreises, seine Größe, Position usw. verändern indem wir Methoden des ''Circle''-Objekts aufrufen. Dazu weisen wir das Objekt (eigentlich: eine Referenz darauf, siehe später) einer Objektvariablen zu:
 +<code learnj>
 +   Circle k = new Circle(250, 200, 100);
 +</code>
 +Der Datentyp der Objektvariable ''k'' ist ''Circle'', weil sie auf ein ''Circle''-Objekt verweist. Genaugenommen liegt das ''Circle''-Objekt irgendwo im Arbeitsspeicher Deines Computers und ''k'' enthält die Anfrangsadresse dieses Speicherbereichs. Mithilfe der Punktschreibweise können wir jetzt Methoden des ''Circle''-Objekts aufrufen:
 +<HTML>
 +
 +<div class="java-online" style="height: 300px; width: 100%" data-java-online="{'withBottomPanel': false, 'id': 'Objekte2'}">
 +
 +<script type="text/plain" title="Objekte1.java">
 +Circle k = new Circle(250, 200, 100);
 +k.setFillColor(Color.red);
 +k.move(100, -50);
 +</script>
 +</div>
 +</HTML>
 +
 +Führe das Programm in Einzelschritten aus ("Step over": {{:klassen1:anwenden:step_over.png?nolink|}}) und ergänze dann ab Zeile 4 selbst weitere Methodenaufrufe!
 +
 +<WRAP center round tip 80%>
 +Der Editor hilft Dir beim Tippen, indem er Dir basierend auf Deinen Eingaben laufend Vorschläge macht ([[https://en.wikipedia.org/wiki/Intelligent_code_completion|code completion]], siehe das kleine gif-Video unter diesem Text). Du kannst die Vorschläge mit den **Tasten Pfeil rauf/Pfeil runter auswählen** und mit der **Tabtaste** oder der **Enter-Taste übernehmen**. Bei der Übernahme einer Methode fügt der Editor dann Platzhalter für die Parameter ein (z.B. "Color", "alpha", ...). Mit der Tab-Taste springst Du von einem Parameter zum nächsten. \\ 
 +
 +{{ :klassen1:anwenden:code_completion.gif |}}
 +</WRAP>
 +
 +==== Beispiel 1: Rakete ====
 +Mit dem Gelernten können wir jetzt schon kleine Animationen erstellen:
 +<HTML>
 +
 +<div class="java-online" style="height: 300px; width: 100%" data-java-online="{'withBottomPanel': false, 'id': 'Objekte3'}">
 +
 +<script type="text/plain" title="Objekte1.java">
 +Triangle spitze = new Triangle(400, 400, 380, 450, 420, 450); // Koordinaten der Eckpunkte in der Reihenfolge x1, y1, x2, y2, x3, y3
 +spitze.setFillColor(Color.white);
 +Rectangle tank = new Rectangle(380, 450, 40, 100);
 +tank.setFillColor(Color.lightblue);
 +Triangle triebwerk1 = new Triangle(385, 550, 375, 580, 395, 580);
 +triebwerk1.setFillColor(Color.gray);
 +Triangle triebwerk2 = new Triangle(415, 550, 405, 580, 425, 580);
 +triebwerk2.setFillColor(Color.gray);
 +
 +for(int i = 0; i < 600; i++) {
 +   spitze.move(0, -1);                // Ungünstig, siehe den weiteren Text!
 +   tank.move(0, -1);
 +   triebwerk1.move(0, -1);
 +   triebwerk2.move(0, -1);
 +}
 +</script>
 +</div>
 +</HTML>
 +==== Verbesserung: Group-Objekt ====
 +Dass im obigen Programm die Bestandteile der Rakete einzeln verschoben werden müssen, ist sehr ungünstig. Bei langsamer Ausführungsgeschwindikeit sieht man die Teile sogar einzeln vorwärtsruckeln. Und stell' Dir vor, wir wollten die Rakete um ihren Schwerpunkt drehen: Was würde passieren, wenn ab Zeile 11 steht:
 +<code learnj>
 +spitze.drehen(2);
 +tank.drehen(2);
 +triebwerk1.drehen(2);
 +triebwerk2.drehen(2);
 +</code>
 +Probier' es doch mal aus (Copy/Paste...)! \\ \\ 
 +Die Lösung der Probleme besteht darin, die einzelnen Objekte zu gruppieren, genauso wie in vektororientierten Zeichenprogrammen. Zu diesem Zweck gibt es die Klasse ''Group'':
 +
 +<HTML>
 +
 +<div class="java-online" style="height: 300px; width: 100%" data-java-online="{'withBottomPanel': false, 'id': 'Objekte4'}">
 +
 +<script type="text/plain" title="Objekte1.java">
 +Triangle spitze = new Triangle(400, 400, 380, 450, 420, 450); // Koordinaten der Eckpunkte in der Reihenfolge x1, y1, x2, y2, x3, y3
 +spitze.setFillColor(Color.white);
 +Rectangle tank = new Rectangle(380, 450, 40, 100);
 +tank.setFillColor(Color.lightblue);
 +Triangle triebwerk1 = new Triangle(385, 550, 375, 580, 395, 580);
 +triebwerk1.setFillColor(Color.gray);
 +Triangle triebwerk2 = new Triangle(415, 550, 405, 580, 425, 580);
 +triebwerk2.setFillColor(Color.gray);
 +
 +Group rakete = new Group();
 +rakete.add(spitze, tank, triebwerk1, triebwerk2);
 +
 +for(int i = 0; i < 600; i++) {
 +   rakete.move(0, -1);
 +}
 +</script>
 +</div>
 +</HTML>
 +
 +
 +===== Genaue Betrachtung: Objektreferenzen und Objekte =====
 +Schau' Dir folgendes Beispielprogramm an:
 +<HTML>
 +
 +<div class="java-online" style="height: 300px; width: 100%" data-java-online="{'id':'Objekte5'}">
 +
 +<script type="text/plain" title="Main.java">
 +Rectangle r;                          // Deklarieren der Variable r vom Typ Rectangle
 +r = new Rectangle(10, 10, 400, 200);  // Instanzieren eines neuen Rechteck-Objekts und Zuweisen zu r
 +                                      // r zeigt jetzt auf das Rechteck-Objekt.
 +Rectangle k;
 +k = r;                                // Der Wert von r (d.h. die Adresse des Rechteck-Objekts) wird in die Variable k hineinkopiert
 +k.setFillColor(Color.red);            // Aufruf der Methode "setFillColor" von r; Übergabe es Parameterwertes Color.red
 +r.rotate(30);                         // Aufruf der Methode "rotate" von r; Übergabe des Parameterwertes 30
 +</script>
 +</div>
 +
 +</HTML>
 +
 +Wie viele ''Rectangle''-Objekte gibt es in diesem Programm? Was bewirkt die Anweisung ''k = r''? \\ \\ 
 +Zum Vergleich ein ähnliches Programm mit ''int''-Variablen:
 +<HTML>
 +
 +<div class="java-online" style="height: 300px; width: 100%" data-java-online="{'id':'Objekte6'}">
 +
 +<script type="text/plain" title="Main.java">
 +int r;                                // Deklarieren der Variable r vom Datentyp int
 +r = 10;                               // Instanzieren eines neuen Rechteck-Objekts und Zuweisen zu r
 +                                      // r zeigt jetzt auf das Rechteck-Objekt.
 +int k;
 +k = r;                                // Der Wert von r wird in die Variable k hineinkopiert
 +k = k * 2;
 +println("r: " + r);
 +println("k: " + k);
 +</script>
 +</div>
 +
 +</HTML>
 +Was gibt das Programm aus? \\ 
 +
 +Eine ausführliche Erklärung für dieses merkwürdige Phänomen findest Du auf [[.objektreferenzen:start|dieser extra-Seite]].
 +
 +
 +
 +===== Instanzieren der "Welt" =====
 +Damit graphische Objekte ausgegeben werden können, muss zunächst die Grafikausgabe "geöffnet" werden. Dies geschieht durch Instanzieren eines Objektes der Klasse World, z.B.:
 +<code learnj>
 +new World(800, 600);
 +</code>
 +Die übergebenen Koordinaten (800, 600) sind die Koordinaten der rechten unteren Ecke der Welt. Dabei ist zu beachten, dass die positive y-Achse - wie bei Computersystemen meist üblich - nach unten zeigt. Hier eine des Welt-Koordinatensystems:
 +{{ :klassen1:anwenden:pasted:20200504-135125.png }} 
 +
 +Falls Du vergisst, ein Welt-Objekt zu instanzieren, wird das **vom System automatisch nachgeholt, sobald das erste graphische Objekt instanziert wird**. In diesem Fall werden die Grenzen des Koordinatensystems automatisch (wie oben) bei x = 800 und y = 600 gesetzt.
 +
 +==== Beispiel 2: gedrehte Rechtecke ====
 +<HTML>
 +
 +<div class="java-online" style="height: 300px; width: 100%" data-java-online="{'id': 'Objekte7'}">
 +
 +<script type="text/plain" title="Main.java">
 +new World(800, 600);
 +for(int i = 0; i < 36; i++){
 +   Rectangle r = new Rectangle(450, 300, 150, 100);
 +   r.setAlpha(0.2);
 +   r.rotate(10*i, 400, 300);
 +}</script>
 +</div>
 +
 +</HTML>
 +
 +Jedes der 36 Rechtecke hat initial dieselbe Position. Das erste wird um 10° um mit Drehpunkt (400,300) gedreht, das zweite um 20°, das dritte um 30° usw. Hier eine Schemadarstellung:
 +{{ :klassen1:anwenden:pasted:20200504-161013.png }}
 +
 +==== Beispiel 3: Sinuskurve ====
 +<HTML>
 +<div class="java-online" style="height: 300px; width: 100%" data-java-online="{'id': 'Objekte8'}">
 +
 +<script type="text/plain" title="Main.java">
 +new World(800, 600);
 +for(int i = 0; i < 80; i++){
 +   Circle c = new Circle(10*i, 300 + 200*Math.sin(i/5.0), 20);
 +   c.setFillColor(Color.white);
 +   c.setAlpha(0.2);
 +}
 +</script>
 +</div>
 +</HTML>
 +
 +Die Parameter beim Instanzieren von ''Circle''-Objekten haben folgende Bedeutung: ''Circle(mitteX, mitteY, radius)''. Die x-Koordinate erhöht sich von Kreis zu Kreis in 10'er Schritten, der Radius bleibt konstant 20. Der Term für die y-Koordinate ''300 + 200*Math.sin(i/5.0)'' sorgt für die sinusförmige Kurve.
 +
 +==== Beispiel 4: Farbige Rechtecke ====
 +<HTML>
 +<div class="java-online" style="height: 350px; width: 100%" data-java-online="{'id': 'Objekte9', 'withBottomPanel': false}">
 +
 +<script type="text/plain" title="Main.java">
 +for(int zeile = 0; zeile < 10; zeile++) {
 +   for(int spalte = 0; spalte < 10; spalte++) {
 +      
 +      Rectangle r = new Rectangle(spalte * 50 + 30, zeile * 50 + 30, 40, 40);
 +      
 +      double alpha = Math.abs(zeile - spalte) / 3.0;
 +      r.setFillColor(new Color(zeile * 25, 0, spalte * 25), alpha);
 +      r.rotate((zeile + spalte) * 10);
 +
 +   }
 +}
 +</script>
 +</div>
 +</HTML>
 +
 +<WRAP center round tip 100%>
 +**Neue Farben "mischen":** \\ 
 +Du kannst nicht nur die vorgegebenen Farbwerte (''Color.red, Color.yellow, ...'') verwenden, sondern auch beliebige andere Farben erzeugen, indem Du den Rot-, Grün- und Blauwert der Farbe angibst. Die einzelnen Werte dürfen dabei zwischen 0 und 255 liegen. Das folgende Programm erzeugt ein Rechteck-Objekt und färbt es mit einer Farbe, deren Rotwert 100, Grünwert 20 und Blauwert 87 beträgt.
 +<code myjava>
 +   Rectangle r = new Rectangle(10, 10, 100, 100);
 +   r.setFillColor(new Color(100, 20, 87));
 +</code>
 +**Wie kommen die Farben zustande?** \\ 
 +Computerdisplays bedienen sich eines Tricks zur Farbdarstellung: Da das menschliche Auge nur Farbsensoren für rotes, grünes und blaues Licht hat ("Zäpfchen" auf der Netzhaut), reicht es, nur diese drei Sensortypen einzeln in unterschiedlicher Intensität zu aktivieren, um alle für den Menschen sichtbaren Farbeindrücke hervorzurufen. 
 +{{ :klassen1:anwenden:pasted:20201015-093719.png?200}}
 + \\ \\ Displays bestehen daher aus vielen sehr kleinen roten, grünen und blauen Punkten, deren Helligkeit einzeln geregelt werden kann. Je drei davon werden zu einem Bildpunkt ("Pixel") zusammengefasst. Die Angabe der Rot- Grün- und Blauwerte oben regelt die Helligkeit der jeweiligen Teilpunkte des Pixels. Dabei steht der Wert ''0'' für "Bildpunkt schwarz" und 255 für "Bildpunkt hat maximale Helligkeit"
 + \\ \\ Die vom Auge wahrgenommene Farbe des Pixels entspricht der **additiven** Mischfarbe der drei Teilpunkte. Diese Art der Farbmischung wird für dich ungewohnt sein, weil die Mischfarben von Farbstiften und Wasserfarben **subtraktiv** zustandekommen. Eine gute Erklärung der beiden Arten von Farbmischung findest Du in den Wikipedia-Artikeln zu [[https://de.wikipedia.org/wiki/Additive_Farbmischung|additiver]] und [[https://de.wikipedia.org/wiki/Subtraktive_Farbmischung|subtraktiver Farbmischung]].
 + \\ \\ 
 +**Kleines Experiment:** \\ 
 +Halte ein Fernglas **in umgedrehter Richtung** ganz nah an den Bildschirm, dann kannst Du die roten, grünen und blauen Punkte deutlich sehen. Schau' Dir so verschiedenfarbige Flächen am Bildschirm an und beobachte die Intensität der farbigen Teilpunkte. 
 +
 +</WRAP>
 +
 +
 +==== Aufgabe 1: "Auto" ====
 +{{ :klassen1:anwenden:pasted:20200504-175448.png}}
 +Schreibe ein Programm, das ein einfaches Auto (siehe Bild rechts) zeichnet und es dann von links nach rechts fahren lässt!
 +<HTML>
 +<div style="clear: both; height: 10px"></div>
 +<div class="java-online" style="height: 400px; width: 100%" data-java-online="{'id':'ObjekteAufgabe1'}">
 +
 +<script type="text/plain" title="Main.java">
 +// Auto-Aufgabe: Hier programmieren:
 +</script>
 +
 +<script type="text/plain" title="Tipp 1", data-type="hint">
 +## Tipp 1:
 +  - Du brauchst zwei Objekte der Klasse `Kreis` und ein Objekt der Klasse `Rechteck`.
 +  - Damit das Auto sich ruckelfrei bewegt solltest Du wie im verbesserten Raketenprogram oben die Klasse `Group` verwenden.
 +</script>
 +
 +
 +<!-- 
 +<script type="text/plain" title="Main.java">
 +new World(800, 600);
 +for(int i = 0; i < 30; i++){
 +   Circle c = new Circle(400, 20*i, 2*i);
 +   c.setFillColor(Color.red);
 +   c.setAlpha(0.2);
 +}
 +</script>
 +-->
 +</div>
 +</HTML>
 +[[.autoLoesung:start|Hier geht's zur Lösung!]]
 +
 +==== Aufgabe 2: Farbkreise ====
 +Schreibe ein Programm, das drei Farbkreise wie im folgenden Video zeichnet und dann drehen lässt!
 +{{ :klassen1:anwenden:farbkreise.gif |}}
 +<HTML>
 +<div class="java-online" style="height: 400px; width: 100%" data-java-online="{'id':'ObjekteAufgabe2'}">
 +<script type="text/plain" title="Main.java">
 +// Farbkreise: Hier programmieren:
 +</script>
 +<!-- 
 +<script type="text/plain" title="Main.java">
 +Circle kreisRot = new Circle(400, 170, 150);
 +kreisRot.setFillColor(Color.red, 0.5);
 +
 +Circle kreisGelb = new Circle(400, 170, 150);
 +kreisGelb.setFillColor(Color.yellow, 0.5);
 +kreisGelb.rotate(120, 400, 300);
 +
 +Circle kreisBlau = new Circle(400, 170, 150);
 +kreisBlau.setFillColor(Color.blue, 0.5);
 +kreisBlau.rotate(240, 400, 300);
 +
 +Group figur = new Group();
 +figur.add(kreisRot, kreisGelb, kreisBlau);
 +
 +while(true) figur.rotate(1);
 +</script>
 +-->
 +<script type="text/plain" title="Tipp", data-type="hint">
 +## Tipp:
 +  - Die Klasse `Circle` besitzt eine Methode `setFillColor`, die als Parameter eine Farbe und einen Alpha-Wert ("Durchsichtigkeit!") erwartet, z.B. `kreis.setFillColor(Color.blue, 0.5);`
 +  - Verwende wieder ein `Group`-Objekt, um die Kreise zu gruppieren und drehe dann dieses mit Hilfe der Methode `rotate`.
 +</script>
 +</div>
 +</HTML>
 +
 +[[.farbkreiseLoesung:start|Hier geht's zur Lösung!]]
  
klassen1/anwenden/start.txt · Zuletzt geändert: 2024/08/31 12:03 von 127.0.0.1