34
6. Eventhandling in Java – OO-Graphics in Java – Eventhandling in Java 143

6. Eventhandling in Java - inf.fu-berlin.de · Java 1.1 vs. Java 1.0 Achtung (wichtige Warnung): Das Eventhandling von Java 1.1 unter-scheidet sich wesentlich vom Event-handling in

  • Upload
    others

  • View
    8

  • Download
    0

Embed Size (px)

Citation preview

6. Eventhandlingin Java

– OO-Graphics in Java – Eventhandling in Java 143

Eventhandling in Java

Bisher:

� OO-Grundlagen,

� Programmablauf,

� Zeichenmoglichkeiten,

� Anordnung von Bedienelementen.

Was fehlt?

Interaktivitat !!!

– OO-Graphics in Java – Eventhandling in Java 144

Worauf ein Programmreagieren muss

Low-Level:

� Tastatureingaben,� Maus-Ereignisse,� Timer-Ereignisse.

High-Level:

� Fenster schliessen/offnen,� Grossenveranderungen,� Knopf auf Bildschirm gedruckt,� Text editiert,� �����

– OO-Graphics in Java – Eventhandling in Java 145

Java 1.1 vs. Java 1.0

Achtung (wichtige Warnung):

Das Eventhandling von Java 1.1 unter-scheidet sich wesentlich vom Event-handling in Java 1.0.

Java 1.0 Stil ist in Java 1.1 zwar nochmoglich, aber nicht empfohlen (depre-cated).

Im folgenden wird Java 1.1 Stil vermit-telt.

Java 1.1 wird von Netscape 4.06, vonInternet Explorer 4.01 und von Hotjava(Sun Browser) unterstutzt.

– OO-Graphics in Java – Eventhandling in Java 146

Event

Event: Das Eintreten eines Ereignisses, auf welches das Pro-gramm reagieren muss (z.B. Tastendruck, Mausbewegung, ����� ).

Event-Quelle: Events werden immer dem Component-Objekt zu-geordnet, in dem sie entstehen — der “Event-Quelle”.

Event-Objekt: Das Auftreten eines Events ist verbunden mit derErzeugung eines Objektes. Dieses Objekt gehort einer der Unter-klassen von AWTEvent an. Es enthalt alle notwendigen Informatio-nen uber das Event.

Event-Listener: Component-Objekte speichern eine Liste vonEventListener-Objekten ab. Dies sind Objekte, die uber das Auf-treten eines Events “benachrichtigt” werden sollen. Die ListenerObjekte sind jeweils spezialisiert auf bestimmte Event-Klassen.

Event-Action: Beim Auftreten eines Events veranlasst die Event-

Quelle den Aufruf einer standardisierten (dem Event zugeord-

neten) Methode bei allen fur diesen Event-Typ angemeldeten

Listener-Objekten. Der Aufruf dieser Methoden ist dem Event

selbst gleichzusetzen!

– OO-Graphics in Java – Eventhandling in Java 147

Das awt.event package

1995-7, Charles L. Perkins http://rendezvous.com/java

Objectjava.lang

java.awt.event

ComponentListener

FocusListener

KeyListener

MouseListener

MouseMotionListener

WindowListener

ActionListener

AdjustmentListener

ItemListener

EventObjectjava.util

AWTEventjava.awt-events

EventListenerjava.util

ActionEvent

AdjustmentEvent

ComponentAdapter

ComponentEvent

FocusAdapter

FocusEvent

InputEvent

ItemEvent

KeyAdapter

KeyEvent

MouseAdapter

MouseEvent

MouseMotionAdapter

PaintEvent

WindowAdapter

WindowEventSerializablejava.io-objects

AWTEventMulticaster

Objectjava.lang

Event

EventDispatchThreadlocal to package

Threadjava.lang

EventQueue

EventQueueItemlocal to package

EventObjectjava.util

AWTEvent

Serializablejava.io-objects

java.awt-eventss

ContainerListener

TextListener

ContainerAdapter

ContainerEvent

TextEvent

– OO-Graphics in Java – Eventhandling in Java 148

Event-Objekte

AWTEvent-Objekt � ���

����� ist ein Objekt welches das Auftreten eines Ereig-nisses beschreibt,

����� enthalt alle notwendigen Informationen, die dasEreignis betreffen (Wo? Wann? Wer? ��� � ),

����� ist quasi ein Brief von der Ereignisquelle an alleInteressenten.

����� besitzt zahlreiche Unterklassen, die spezia-lisierte Ereignisse beschreiben (MouseEvent,MouseMotionEvent, KeyEvent, WindowEvent,ActionEvent, � ��� )

– OO-Graphics in Java – Eventhandling in Java 149

Event Zyklus in Java-1.1

Erzeugung: Component-Objekte sind die Event-Quellen. Tritt ein zu einer Component gehoriges Ereig-nis auf (z.B. “Knopf-gedruckt” auf einem Button oder“Mouse-Drag” in einer Canvas), so wird ein entspre-chendes AWTEvent-Objekt erzeugt.

Verschicken: Jede Component hat eine Liste vonEventListener-Objekten. An diese wird das AWTEvent“verschickt” (d.h. bestimmte Methoden werden aufgeru-fen).

Verarbeitung: Die EventListener-Objekte mussenMethoden definieren, die auf das Verschicken des Er-eignisses reagieren konnen. Ein EventListener kannein Event als “abgearbeitet” markieren.

Consumed: Ein AWTEvent-Objekt ist “aufgebraucht”(consumed), wenn es an alle potentiellen Listener ver-schickt wurde.

– OO-Graphics in Java – Eventhandling in Java 150

Was passiert, wenn ein Knopfgedruckt wird ?

Press Me Knopf mittels Maus aktiviert

ButtonMouseclick veranlasst den

Button ein AWTEvent:

ActionEvent

zu erzeugen.

Dies Event wird an alle

ActionEventListener

des Buttons geschickt

listener.actionPerformed(event)

event

ActionEventHat alle Information

bzgl. Event- u.Eventquelle

und einen Identifier

der ausgefuehrten

Aktion.

MyAction-Listener

implementiert die Methode

actionPerformed()

in welcher festgelegt ist,

was bei Eintreten des

Events passieren soll

Die Klasse MyActionListener ist das einzige selbst-geschriebene Objekt in diesem Beispiel.

– OO-Graphics in Java – Eventhandling in Java 151

MyActionListener

Im selbst geschriebenen Code von MyActionListenerist festgelegt, was beim Auftreten eines ActionEventsgeschehen soll.

Die Klasse MyActionListener implementiert das In-terface ActionListener.

Dies erzwingt, dass in der Klasse MyActionListenerdie Methode actionPerformed implementiert ist.

Source-Code Gerust:

import java.awt.event.*;

public class MyActionListener implements ActionListener{

public void actionPerformed(ActionEvent e){.....

}.....

}

– OO-Graphics in Java – Eventhandling in Java 152

Event � Methodenaufruf

Ein Eventist der Aufruf einer Methode

in einem EventListener.

Bei dem Methodenaufruf wirdein Objekt der Klasse

AWTEvent als Parameter ubergeben.

Das AWTEvent-Objekt enthaltweitere Information uberdas eingetretene Event.

– OO-Graphics in Java – Eventhandling in Java 153

Programm-Beispiel furActionEvent

Ziel: Ein Button, der eine Zahlvariable hochzahlt undderen Inhalt auf dem Bildschirm anzeigt.

Code fur das Applet:

import java.awt.*; // verwendete Packagesimport java.awt.event.*;import java.applet.*;

public class CountApplet extends Applet {

public int count=0;public Label label = new Label("0");

public void init() {

setLayout(new FlowLayout());Button b = new Button("Press Me");b.addActionListener(new MyActionListener(this)); // <---ADD LISTENERadd(b);add(label);

}}

Hier werden in der Initialisierung lediglich der Button und das

Label zum Anzeigen bereitgestellt. Der Button erhalt einen

selbstdefinierten ActionListener namens MyActionListener.

– OO-Graphics in Java – Eventhandling in Java 154

Der Code furMyActionListener

Der Listener MyActionListener erhoht beim Auftre-ten des ActionEvents die Zahlervariable count des Ap-plets. Dann veranlasst er, dass der zugehorige Text er-zeugt wird, und erzwingt ein repaint des Applets.

Code fur den Listener:

import java.awt.event.*;

public class MyActionListener implements ActionListener{private CountApplet app;MyActionListener(CountApplet app) {this.app=app;

}

public void actionPerformed(ActionEvent e){app.count++;String s=(new Integer(app.count)).toString();app.label.setText(s);app.label.invalidate(); // Layout ist ungultigapp.validate(); // erzwinge neues Layoutapp.repaint(); // Zeichenanforderung

}}

Press Me 5

– OO-Graphics in Java – Eventhandling in Java 155

Erweiterte Version zum Auf- undAbzahlen

public class CountApplet extends Applet {

public int count=0;public Label label = new Label("0");public void init() {

setLayout(new FlowLayout());Button b1 = new Button("Increment");b1.addActionListener(new MyActionListener(1,this));Button b2 = new Button("Decrement");b2.addActionListener(new MyActionListener(-1,this));add(b1);add(b2);add(label);

}}

public class MyActionListener implements ActionListener{CountApplet app;private int step;MyActionListener(int st,CountApplet app) {this.app =app; step=st;

}

public void actionPerformed(ActionEvent e){app.count=app.count+step;String s=(new Integer(app.count)).toString();app.label.setText(s);app.label.invalidate();app.validate();app.repaint();

}}

Increment Decrement 5

– OO-Graphics in Java – Eventhandling in Java 156

Ubergabe von Information

Im Beispiel des Applets CountApplet kam es ledig-lich darauf an, dass uberhaupt ein ActionEvent auf-trat. Es wurde keine Information aus dem Event-Objektentnommen.

(In unserer “Briefmetapher”: Allein das Eintreffen desBriefes loste die Reaktion (hochzahlen) aus. Der Briefmusste gar nicht erst gelesen werden.)

Oftmals ist es allerdings notwendig, die im Eventubergebene Information abzufragen. Als “Informations-behalter” stellt AWTEvent diverse spezialisierte Unter-klassen bereit.

– OO-Graphics in Java – Eventhandling in Java 157

Count-Applet mit Lesen desEvents

Die folgende Increment/Decrement-Version stellt durchLesen der Button-Beschriftung fest, ob ab- oder auf-gezahlt werden soll.

Code des MouseListeners:

import java.awt.event.*;

public class MyActionListener implements ActionListener{private CountApplet app;MyActionListener(CountApplet app){this.app=app;

}

public void actionPerformed(ActionEvent e){if (e.getActionCommand().equals("Increment")) {//<<<< LESEN

app.count=app.count+1;}if (e.getActionCommand().equals("Decrement")) {//<<<< LESEN

app.count=app.count-1;}

String s=(new Integer(app.count)).toString();app.label.setText(s);app.label.invalidate();app.validate();app.repaint();

}}

– OO-Graphics in Java – Eventhandling in Java 158

Unterklassen von AWTEvent

Object

AWTEvent

ActionEvent

AdjustmentEvent

ComponentEvent

ItemEvent

TextEvent

ContainerEvent

FocusEvent

InputEvent

PaintEvent

WindowEvent

MouseEvent

KeyEvent

nicht instantiierbares abstraktes Objekt

instantiierbares Objekt

Die Unterklassen von AWTEvent sind spezialisierte“Datenbehalter”, fur die verschiedenen Ereignisse.

– OO-Graphics in Java – Eventhandling in Java 159

Beispiel: Methoden vonMouseEvent (I)

MouseEvent hat in der Klassenhierarchie die Position

AWTEvent � ComponentEvent � InputEvent � MouseEvent

MouseEvent besitzt u.a. die folgenden Methoden:

getClickCount(): Anzahl der Mouseclicks.

getPoint(): � x � y � -Position des Events relativ zur “Quell-component”.

getX(): x-Komponente des Events relativ zur “Quell-component”.

getY(): y-Komponente des Events relativ zur “Quell-component”.

isPopupTrigger(): Erzeugt das Event ein Pop-Up-Menu?

translatePoint(int, int): Verandert das Koordinatensystem des Events.

– OO-Graphics in Java – Eventhandling in Java 160

Beispiel: Methoden vonMouseEvent (II)

Die Oberklassen vom MouseEvent stellen zudem u.a.folgende Methoden zur Verfugung:

InputEvent:

getModifiers(): Liefert Modifizier-Flags fur das Ereignis.

getWhen(): Systemzeit zu der das Ereignis stattfand.

isAltDown(), isControlDown(), isMetaDown(), isShiftDown():

Wurden modifizierende Tasten gedruckt?

ComponentEvent:

getComponent(): Quell-Component, die das Event verursacht hat.

AWTEvent:

getID(): Event-Typ

Event: getSource(): Event-Quelle

– OO-Graphics in Java – Eventhandling in Java 161

Listener

Listener �����

����� sind Interfaces welche bestimmte Ereignisklas-sen gegeneinander abgrenzen (z.B. die Klasseder ActionEvents, MouseEvents, � ��� ),

����� legen Methoden fest, auf die man fur eineEreignisklasse reagieren konnen muss (z.B.actionPerformed() fur ActionEvents),

����� hat folgende Unterinterfaces:ActionListener, AdjustmentListener, ComponentListener,

ContainerListener, FocusListener, ItemListener,

KeyListener, MouseListener, MouseMotionListener,

TextListener, WindowListener.

����� Components-Objekte sind mit addXListener-Methoden ausgestattet, mittels derer einXListener angemeldet werden kann(z.B. addActionListener(myListener) ummyListener als ActionListener anzumelden).

– OO-Graphics in Java – Eventhandling in Java 162

Methoden der Listener

Listener Methoden mogliche Components

ActionListener actionPerformed ButtonListMenuItemTextField

AdjustmentListener adjustmentValueChanged ScrollbarComponentListener componentHidden Component

componentMovedcomponentResizedcomponentShown

ContainerListener componentAdded ContainercomponentRemoved

FocusListener focusGained ComponentfocusLost

ItemListener itemStateChanged CheckboxCheckboxMenuItemChoiceList

KeyListener keyPressed ComponentkeyReleasedkeyTyped

MouseListener mouseClicked ComponentmouseEnteredmouseExitedmousePressedmouseReleased

MouseMotionListener mouseDragged ComponentmouseMoved

TextListener textValueChanged TextComponentWindowListener windowActivated Window

windowClosedwindowClosingwindowDeactivatedwindowDeiconifiedwindowIconifiedwindowOpened

– OO-Graphics in Java – Eventhandling in Java 163

Beispiel: Ein Draw-Applet(erste Version)

Aufgabe: Ein Applet DrawApplet, welches eine Zei-chenoberflache besitzt, auf die man mit der Mauszeichnen kann. Das Zeichnen soll nur bei gedruckterMaustaste erfolgen.

Erster Ansatz (Applet -Code):

import java.awt.*;import java.awt.event.*;import java.applet.*;

public class DrawApplet extends Applet {

public Canvas canv = new Canvas();

public void init() {

setLayout(new BorderLayout());canv.setSize(400,400);canv.setBackground(Color.blue.darker());canv.setForeground(Color.yellow);add("Center",canv);MyMouseListener listener = new MyMouseListener();canv.addMouseListener(listener);canv.addMouseMotionListener(listener);

}}

– OO-Graphics in Java – Eventhandling in Java 164

Der MouseListener (I)

import java.awt.*;import java.awt.event.*;

public class MyMouseListener implements MouseListener,MouseMotionListener{

public Point p=new Point(0,0);

MyMouseListener() {}

public void mouseClicked(MouseEvent e){}public void mouseEntered(MouseEvent e){}public void mouseExited(MouseEvent e){}public void mouseMoved(MouseEvent e){}public void mouseReleased(MouseEvent e){}

public void mousePressed(MouseEvent e){p= new Point(e.getPoint());

}

public void mouseDragged(MouseEvent e){Canvas canv = (Canvas)e.getSource();Graphics g = canv.getGraphics();g.drawLine(p.x,p.y,e.getX(),e.getY());p= new Point(e.getPoint());

}}

Ein mouseDragged Ereignis bewirkt sofortiges Malenauf derappleteigenen Canvas canv.

– OO-Graphics in Java – Eventhandling in Java 165

Kritik an der ersten Version

Die gemalte Zeichnung ist nirgends abgespeichert.

Ein paint (welches vom Window-Manager jederzeitgeschickt werden kann) bewirkt ein sofortiges Loschender Zeichnung.

Abhilfe:

� Die Zeichnung wird irgendwo gespeichert (entwederals bitmap oder in Form der Koordinaten der gemal-ten Linienstucke).

� Man schreibt eine Unterklasse MyCanvas der vomAWT bereitgestellten Klasse Canvas. Die Unterklas-se MyCanvas besitzt eine eigene paint()-Methode,die fur das Malen der bisherigen Zeichnung sorgt.

– OO-Graphics in Java – Eventhandling in Java 166

Draw-Applet zweite Version

Code fur DrawApplet und fur MyCanvas:

import .....public class DrawApplet extends Applet {

public MyCanvas canv = new MyCanvas(); // <<<< AENDERUNG !!!!

public void init() {setLayout(new BorderLayout());canv.setSize(400,400);canv.setBackground(Color.blue.darker());canv.setForeground(Color.yellow);add("Center",canv);MyMouseListener listener= new MyMouseListener(canv);//<<< AENDERUNGcanv.addMouseListener(listener);canv.addMouseMotionListener(listener);

}}

import java.awt.*;import java.util.*;

public class MyCanvas extends Canvas {

public Vector startpoints = new Vector(); // Lokaler Speicherpublic Vector endpoints = new Vector(); // Lokaler Speicher

public void paint(Graphics g) { // Zeichenmethodefor (int i=0;i<startpoints.size();i=i+1){

Point p1=(Point)startpoints.elementAt(i);Point p2=(Point)endpoints.elementAt(i);g.drawLine(p1.x,p1.y,p2.x,p2.y);

}}

}

– OO-Graphics in Java – Eventhandling in Java 167

Der MouseListener (II)

import .....

public class MyMouseListener implements MouseListener,MouseMotionListener{

private MyCanvas canv; // <<<< AENDERUNG !!!!public Point p=new Point(0,0);

MyMouseListener(MyCanvas a){ // <<<< AENDERUNG !!!!canv=a;

}

public void mouseClicked(MouseEvent e){}public void mouseEntered(MouseEvent e){}public void mouseExited(MouseEvent e){}public void mouseMoved(MouseEvent e){}public void mouseReleased(MouseEvent e){}

public void mousePressed(MouseEvent e){p= new Point(e.getPoint());

}

public void mouseDragged(MouseEvent e){canv.startpoints.addElement(p); // Abspeichern statt Zeichnenp= new Point(e.getPoint());canv.endpoints.addElement(p); // Abspeichern statt Zeichnencanv.repaint(); // Zeichnen erzwingen

}}

Der wesentliche Unterschied gegenuber der ersten Version be-steht darin, dass nicht mehr direkt auf einer Canvas gemaltwird. Vielmehr wird die Zeicheninformation nur noch durchMyMouseListener in MyCanvas abgespeichert und von ihr bei Be-darf gemalt.

– OO-Graphics in Java – Eventhandling in Java 168

Kritik an der zweiten Version

Der Bildschirm flackert !!!

Durch die geanderte Zeichenstrategie ist nun bei je-dem einzelnen mouseDragged Ereignis der (schrittwei-se) Aufbau der kompletten Zeichnung zu sehen.

Die geschieht im allgeneinen zwar sehr schnell, ist beiaufwendigeren Zeichnungen aber als Flackern wahr-nehmbar.

Abhilfe: Einfuhrung von double-buffering.

� Der Bildaufbau erfolgt unsichtbar im Hintergrund aufeinem eigens dafur bereitgestellten Stuck Speicher(bitmap).

� Die notwendigen Anderungen konnen alle lokal inder Klasse MyCanvas vorgenommen werden.

– OO-Graphics in Java – Eventhandling in Java 169

Double buffering

Vordergrund Bildaufbau

kopieren

Das neue Bild wird auf einer bitmap (im Speicher) ge-malt. Erst, wenn das Bild fertig ist, wird es im sichtbarenFenster dargestellt.

– OO-Graphics in Java – Eventhandling in Java 170

MyCanvas mit double-buffering

public class MyCanvas extends Canvas {

public Vector startpoints = new Vector();public Vector endpoints = new Vector();

int oldw, oldh;Image backImage; //HintergrundbildGraphics backG; //Graphics von backImage

public void paint(Graphics g) {

Dimension d = getSize();if (d.width != oldw || d.height != oldh ) { //Neuer Speicher notwendig?

if (backImage != null) backImage.flush();backImage = createImage(d.width,d.height);backG = backImage.getGraphics();oldw = d.width;oldh = d.height;

}backG = backImage.getGraphics();backG.setColor(getBackground()); //Alles im Hintergrund malenbackG.fillRect(0,0,oldw,oldh);backG.setColor(getForeground());for (int i=0;i<startpoints.size();i=i+1){

Point p1=(Point)startpoints.elementAt(i);Point p2=(Point)endpoints.elementAt(i);backG.drawLine(p1.x,p1.y,p2.x,p2.y);

}g.drawImage(backImage,0,0,this); //nach vorne kopieren

}

public void update(Graphics g) { //muss ueberschrieben werden paint(g);}

}

– OO-Graphics in Java – Eventhandling in Java 171

Checkbox — CheckboxGroup

Oft ist es notwendig mehrere Schalter zu erzeugen,mittels derer man zwischen verschiedenen Betriebs-zustanden des Programmes umschalten kann.

Der folgende Code erzeugt Radio-Button Verhalten:

import java.applet.Applet;import java.awt.*;

public class CheckBoxApplet extends Applet {

public void init() {

setBackground(Color.lightGray);

Panel controls = new Panel(new GridLayout(1,3));

CheckboxGroup cg = new CheckboxGroup();

Checkbox a = new Checkbox("First" );a.setCheckboxGroup(cg);Checkbox b = new Checkbox("Second" );b.setCheckboxGroup(cg);Checkbox c = new Checkbox("Third" );c.setCheckboxGroup(cg);a.setState(true);

controls.add(a);controls.add(b);controls.add(c);add(controls);

}}

– OO-Graphics in Java – Eventhandling in Java 172

Eventhandling bei Radio-Buttons

Aufgabe: Drei Knopfe mit Radio-Button Verhalten sol-len jeweils individuellen Text im Fenster anzeigen.

import java.applet.Applet;import java.awt.*;

public class CheckBoxApplet extends Applet {

public void init() {

setBackground(Color.lightGray);

Label label = new Label("?????????????????");label.setFont(new Font("Helvetica",Font.BOLD,36));

Panel controls = new Panel(new GridLayout(1,3));

MyCheckboxGroup cg = new MyCheckboxGroup();

MyCheckbox a = new MyCheckbox("First","Erster",label);a.setCheckboxGroup(cg);MyCheckbox b = new MyCheckbox("Second","Zweiter",label );b.setCheckboxGroup(cg);MyCheckbox c = new MyCheckbox("Third","Dritter",label );c.setCheckboxGroup(cg);a.setState(true);

controls.add(a);controls.add(b);controls.add(c);add(controls);add(label);

}}

– OO-Graphics in Java – Eventhandling in Java 173

Code fur MyCheckbox

import java.awt.*;

public class MyCheckbox extends Checkbox {

String pt;Label l;

private MyCheckbox() {}

public MyCheckbox(String text, String printText, Label label) {setLabel(text);pt=printText;l=label;

}

public void deselect( ) { // Hier darf man eigenes} // Verhalten spezifizieren

public void select( ) { // Hier darf man eigenesl.setText(pt); // Verhalten spezifizieren

}}

Die Checkbox wird mit einem select/deselect-Mechanismus ausgestatted. Die Steuerung dieses Me-chanismus wird von der CheckboxGroup ubernommen.

(Hiermit wird zwar das interne Eventhandling umgan-gen, dies ist jedoch sinnvoll. Auf diese Weise wird eindeselect-Verhalten ermoglicht.)

– OO-Graphics in Java – Eventhandling in Java 174

Code fur MyCheckboxGroup

import java.awt.*;import java.awt.event.*;

class MyCheckboxGroup extends CheckboxGroup {

public synchronized void setSelectedCheckbox(Checkbox checkbox) {Checkbox c2 =getSelectedCheckbox();if (c2 != null && c2 instanceof MyCheckbox) {

((MyCheckbox)c2).deselect();}super.setSelectedCheckbox(checkbox);((MyCheckbox)checkbox).select();

}}

Die setSelectedCheckbox-Methode wird vom AWTbeim Drucken eines Knopfs der Buttongroup aufgeru-fen.

Dies ist eine geeignete Stelle um den select/deselect-Mechanismus einzufugen, indem wir das “normale”Verhalten der Methode setSelectedCheckbox ausder Klasse CheckboxGroup mit unserem speziellenVerhalten uberschreiben.

– OO-Graphics in Java – Eventhandling in Java 175

– OO-Graphics in Java – Eventhandling in Java 176