Contains, Klicken

Werbung
Übungsblatt 7
12
Contains Methode
Nun wenn man die geometrische Objekte zeichnen kann, wäre es schön, auch ein Objekt klicken zu
können und z.B. seinen Namen auf dem Bildschirm zu kriegen. Dazu werden wir nun die Methode
contains entwickeln. Die erste Aufgabe ist, die ganzzahlige Koordinaten des Mausklicks zu reellen Koordinaten der geometrischen Objekten umzuwandeln. Wer soll diese Umwandlung machen?
Bestens die Klasse, wo die umgekehrte Aufgabe gelöst wird — GPrim. Man soll dort also eine neue
Methode schreiben:
public static double uCoord(int val) {
return val / koef;
}
Es werden zwei neue Methoden zur Klasse GObject eingefügt: public boolean contains(int
cx, int cy) und protected abstract boolean interneContains(double cx, double cy) . Sie
sollen true zurückliefern, falls die gegebene Koordinaten dem Objekt gehören und sonst false.
Analog mit zeichnen(Graphics) und internesZeichnen() , wird die erste Methode die Daten
vorbereiten während die zweite für alle Unterklassen implementiert und die vorbereitete Daten verarbeiten wird. Die Vorbereitung schließt Umwandlung der Mauskoordinaten zu Koordinatensystem
des Objekts ein:
// ... klasse GObjekt
protected abstract boolean interneContains(double cx, double cy);
public boolean contains(int cx, int cy) {
return interneContains(GPrim.uCoord(cx)-px, GPrim.uCoord(cy)-py);
}
Nun soll man interneContains für die Unterklassen implementieren. Nehmen wir an, dass cx
und cy vorbereitete Koordinaten des Klicks sind und c der Punkt (cx , cy ) ist. Dann gelten die folgende Bedingungen zum Liegen des Punktes c auf einem Objekt:
Punkt p
Strecke a-b
Ellipse e(a, b)
→
→=−
px = cx ∧ py = cy oder −
pc
0
−
→
−
→
ac = α ab, wobei α ∈ [0, 1]
cx 2 cy 2
+ b ≤1
a
Für Dreieck und Viereck muss man aber einen anderen Algorithmus verwenden. Obwohl später
so genannte „Ray casting“-Algorithmus verwendet wird, werden wir uns nun auf die Flächenregel
orientieren. Die Idee ist, dass wenn man das Dreieck ABC und Punkt P ∈ ABC hat, gilt die
folgende Aussage bezüglich der Flächen:
A(ABP) + A(BC P) + A(C AP) = A(ABC )
22
Dreieck’s interneContains
Entsprechend der gegebenen Formel, kann man diese Methode so schreiben:
protected boolean interneContains(double cx, double cy) {
Punkt p = new Punkt(cx, cy);
Dreieck abp = new Dreieck(a, b, p),
bcp = new Dreieck(b, c, p),
cap = new Dreieck(c, a, p);
return GMath.equals(abp.flaeche()+bcp.flaeche()+cap.flaeche(), flaeche());
}
12.2
Autor: M. A.
12.1
Viereck’s interneContains
Beim Viereck kann man zwei Dreiecke bilden: abc und cda. Wenn der Punkt zu einem von
diesen Dreiecke gehört, ist er auch im Viereck.
13
Den Applet klicken
Um die Mouse-events wahrnehmen zu könnnen, soll eine Klasse zuerst die Schnittstelle MouseListener
aus java.awt.event.*; implementieren. In unserem Fall wird es genügen, dass der Applet sich
selbst ein MouseListener wird. Also kehren wir zurück zu unserem Demo.java, und fügen wir da
implements MouseListener ein (nachdem wir das genannte Paket importiert haben). Danach wird
Ihres Program nicht mehr laufen, bevor Sie die gebrauchte Methoden (auch wenn leer!) implementieren. Machen Sie also das für mousePressed, mouseEntered, mouseClicked, mouseExited und
mouseReleased. Alle diese Methoden sind public void und haben MouseEvent e als Argument.
Ihre Körper sind leer.
Damit Sie Ihr neues MouseListener aktiv machen. Sollen Sie nun am Ende der init() Methode
die folgende Zeile einfügen:
addMouseListener(this);
Nach dem ist dieser Applet sich selbst ein MouseListener geworden. Was fehlt, ist die Möglichkeit des Typs ZObjekt, die Methoden contains und art anzubieten. Also werden wir sie da
schreiben:
public interface ZObjekt {
// ...
public boolean contains(int cx, int cy);
public String art();
}
Nun zurück zum Applet. Von allen neu implementierten Methoden werden Sie nur mousePressed
erweitern. Kehren wir zu dieser Methode. Wenn Benutzer den Applet klickt, wird diese Methode
gerufen und aus dem Objekt e können Sie mittels Methoden getX() und getY() die ganzzahlige
Koordinaten des Klicks nehmen. Wenn Sie diese Koordinaten einem ZObjekt über contains(int,
int) geben, erfahren Sie gleich, ob dieses Objekt geklickt wurde. Falls das geschieht, sollen Sie
den Namen des Objekts (Methode art()) auf diesen Koordinaten des Applets schreiben. Da die
23
Methode mousePressed aber nicht zum Zeichnen gemeint ist, muss sie dese Werte irgendwo speichern, damit sie später von der Methode paint() benutzt werden können. Für den Namen werden
wir ein neues Attribut private String artText = ""; benutzen und die Klickkoordinaten werden
in neuen Attributen private int klickX = 0, klickY = 0; gespeichert werden.
Jetzt kann man diese Methode schreiben. Man greift jedem Objekt aus arr zu, und gibt ihm die
Koordinaten des Klicks über Methode contains. Falls man true als Ergebnis bekommt, speichert
man die benötigte Daten, bricht die Suchschleife und ruft die Methode repaint(), sodass der Applet
sein Bild wieder zeichnet. Falls kein Objekt true liefert, soll artText leer bleiben.
public void mousePressed(MouseEvent e) {
artText = "";
for(ZObjekt obj : arr) {
if(obj != null) {
if(obj.contains(e.getX(), e.getY())) {
klickX = e.getX();
klickY = e.getY();
artText = obj.art();
break;
}
}
}
repaint();
}
Nachdem dies gemacht wird, braucht man nur noch die Methode paint so zu erweitern, dass sie
artText zeigt. Zusätzlich kann man artText ignorieren, falls sie leer ist. Also Folgendes soll man
am Ende der paint()-Methode schreiben:
if(!artText.equals("")) {
g.drawString(artText, klickX, klickY);
}
Und es läuft schon.
14
ArrayList
Eine klassische Reihe zu benutzen (wie in unserem Demo-Applet) ist nicht immer bequem. Speziell
wenn die Länge der Reihe nicht im Voraus bekannt ist. Deswegen werden wir die Klasse ArrayList18
aus dem Paket java.util.*; zum Spechern der Objekte benutzen. Es wird Schritt für Schritt
gegeben, welche Änderungen man tun soll. Zuerst soll man die Zeile mit dieser Reihe finden:
private ZObjekt[] arr = {null, null, null};
Und sie mit Folgendem ersetzen:
private ArrayList<ZObjekt> arr = new ArrayList<ZObjekt>();
18
Da diese Klasse für unsere Zwecke sehr intuitiv ist, wird sie hier nicht ausführlich betrachtet. Über sie kann man
mehr unter http://java.sun.com/j2se/1.5.0/docs/api/java/util/ArrayList.html finden
24
Weitere Unterschiede sind bei der Erzeugung der neuen Objekte:
Vor
arr[0] = new Punkt(2,1);
arr[1] = new Dreieck().positionieren(4,4);
arr[2] = new Ellipse(2,1).positionieren(3,2);
Nach
arr.add(new Punkt(2,1));
arr.add(new Dreieck().positionieren(4,4));
arr.add(new Ellipse(2,1).positionieren(3,2));
Falls Sie die Schleife in der Methode paint() noch nicht nach foreach umgewandelt haben, tun
Sie es nun (Musterlösung an der Seite 21. vom Übungsblatt 6). Das soll alles sein. Nun können Sie
weitere Objekte zu arr mittels ihrer Methode add einfügen.
25
Herunterladen