450 likes | 546 Views
Kapitel 13: Graphische Benutzer-Schnittstelle _____________________________________. Elemente graphischer Benutzer-Schnittstellen AWT: GUI-Unterstützung durch Java Ein erstes Fensterprogramm Bedienknöpfe Grafikausgabe in Fenstern Ein Fenster mit Maus Die Methode paint Applets.
E N D
Kapitel 13:Graphische Benutzer-Schnittstelle_____________________________________ • Elemente graphischer Benutzer-Schnittstellen • AWT: GUI-Unterstützung durch Java • Ein erstes Fensterprogramm • Bedienknöpfe • Grafikausgabe in Fenstern • Ein Fenster mit Maus • Die Methode paint • Applets
Graphische Benutzer-Schnittstelle • Interaktive Programme bzw. Programmsysteme zeichnen sich durch die Möglichkeit zur Benutzer-Interaktion (d.h. z.B. Daten-Ein und Ausgabe während des Programmablaufs) aus. • Als Benutzer-Schnittstelle bezeichnet man die Menge der Vereinbarungen und Vorkehrun-gen, die man zum Zwecke der Benutzer-Interaktion trifft. • Bisher haben wir Möglichkeiten zur eindimen-sionalen Daten-Ein und -Ausgabe per Text kennen gelernt. • Eine graphische Benutzer-Schnittstelle (engl.: Graphical User Interface, GUI)beruht auf der sog. "Schreibtisch-Metapher" (desktop metaphor): Der Bildschirm fungiert als zwei-dimensionales Ein- und Ausgabemedium. Daten- Ein und Ausgabe Benutzer Programmsystem Benutzer-Schnittstelle
Elemente einer graphischen Benutzer-Schnittstelle • Bei der Entwicklung der Benutzer-Schnittstelle sind u.a. folgende Aufgaben zu lösen: • - Dialoggestaltung, • - Aufbau und Form der Benutzer-Eingaben, • - Gestaltung von Kommandos, Fenstern, Menüs, Ikonen, .. • - Belegungen der Eingabegeräte (Tastatur, Maus, Joystick, ..) • - Aufbau und Form der Benutzer-Ausgaben (über Bildschirm, Drucker, ..) • Für die Programmierung einer graphische Benutzer-Schnittstelle sind folgende Elemente besonders wichtig: - Fenster und ihre Bestandteile (Menüs, Bedienknöpfe, ..), - Tastatur, Maus und ggf. weitere Eingabegeräte, einschl. ihrer Steuerung, - Ereignisse und ihre Behandlung.
GUI-Unterstützung bei Java: AWT • Moderne Programmier-Umgebungen leisten Unterstützung nicht nur beim Editieren, Übersetzen, Ausführen und Testen von Programmen, sondern auch bei der GUI-Entwicklung durch das Angebot entsprechende Programm- Pakete. • Entscheidend ist dabei die Frage der Plattform- Unabhängigkeit (d.h. Unabhängigkeit vom unterliegenden Basis- / Betriebssystem). • Java ist Plattform-unabhängig nicht nur in Bezug auf das Kernsystem, sondern auch auf die Unterstützung bei der GUI-Entwicklung. • Teil der Java-Programmier-Umgebung ist das Programm-Paket AWT (AbstractWindowing Toolkit, java.awt). Dieses ist Plattform-unabhägig, kann also auf allen Plattformen, auf denen Java implementiert ist, ohne jede Änderung benutzt werden.
GUI-Stilvarianten: Swing -Komponenten • Bei den neueren Versionen der Java-Software (JDK) von SUN gibt es die Möglichkeit, den Stil der GUI zu beeinflussen. Dazu dienen die sog. Swing-Komponenten. • Dabei handelt es sich um vordefinierte Komponenten des Java-Programmiersystems, die die Verwendung der Stil-Familien „Java“, „X-Windows“ und „Microsoft-Windows“ermöglichen. • Damit kann das Erscheinungsbild der GUI durch Auswahl einer spezifischen Swing-Komponente dem gewünschten Stil angepaßt werden. • Darüber hinaus enthält das Paket javax.swingzusätzliche Dienste zur Ausgestaltung komplexer GUI's, z.B. Knöpfe mit Icons, Dialoge zum Dateizugriff, Baumdarstellung für Verzeichnisse, Paßwort-Boxen, Progress Bars und "sliders" (proportionale Anzeige)
Java AWT: Abstract Windowing Toolkit • Java unterstützt die Plattform-unabhägige GUI-Entwicklung durch das Programm-Paket java.awt . AWT: Plattform-unabhängiges API API:Anwendungs-programm-Schnittstelle (Application Programming Interface) Java Virtual Machine Plattform-spezifisches API • Im Paket java.awt sind Klassen und Schnittstellen zum Arbeiten mit Fenstern, Menüs, Bedienknöpfen etc. zusammengefaßt.
Fenster: Die Klasse Frame • Die grafische Ausgabe in Fenstern wird durch eine abstrakte KlasseGraphics beschrieben, in der wichtige grafische Ausgabefunktionen definiert sind. • Ein normales Fenster wird durch die Klasse Frame modelliert. Ein solches Fenster kann vergrössert, verkleinert und verschoben werden. • Es ist ein Behälter, der Menüelemente und Bedienknöpfe als Komponenten aufnehmen kann. • Jedes Fenster kann das Ziel graphischer Ausgaben sein.
Eine einfache Fenster-Klasse (1) • Das folgende Programm ist ein vollständiges, ablauffähiges Programm. • Es erzeugt ein Fenster und wartet dann, bis dieses geschlossen wird. • Wegen der import-Anweisung am Anfang können alle Namendes Paketes AWTdirekt benutztwerden. import java.awt.*; class Fenster extends Frame { Fenster() { super("Fenster zum Hof"); setSize(800, 600); setVisible(true); } } class FensterTester { public static void main(String args[]) { Fenster MainFenster = new Fenster(); } }
Eine einfache Fenster-Klasse (2) • Die Klasse Fensterist als Unterklasse von Framedefiniert . Sie hat einen Konstruktor, der den Text im Titelbalken des Fensters und seine Größe festlegt. • Durch den Aufruf der (von Frame geerbten) Operation setVisiblemit dem Parameter true wird das Fenster sichtbar. Danach wartet das Programm auf irgendein Ereignis. • Die Koordinaten von Fenstern beziehen sich auf ein Koordinatensystem mit einem Nullpunkt in der linken oberen Ecke des aktuellen Fensters. Die Koordinaten sind ganze Zahlen und beschreiben eine Position im Raster von Bildschirmpunkten (Pixeln). x y
Ereignisse (1) • Fenstersysteme werden von Ereignissen gesteuert, auf die das Programm in festgelegter Weise reagiert. • Jede Mausbewegung, jeder Mausklick, jede Tastatureingabe ist ein Ereignis, das eine angemessene Reaktion verlangt. • Dazu kommen Signale des Zeitgebers und Ereignisse, die von anderen Programmteilen ausgelöst werden. • Mögliche Ereignisse: • Tastatur-Eingaben • Mausbewegungen • Betätigen der Maustasten • Zeitgeber-Signale • von anderen Programmteilen ausgelöste Ereignisse
Ereignisse (2) • Zu jedem Zeitpunkt gibt es eine Menge von aktiven Fenstern. Dies sind mit dem new-Operator erzeugte Objekte von Fensterklassen, die noch nicht deaktiviert worden sind. • Ereignisse haben ein Ziel. Primäres Ziel ist immer eines der aktivenFenster. Innerhalb des Zielfensters kann das Ereignis eine Komponente dieses Fensters - z.B. einen Bedienknopf - betreffen. • Ein Ereignis wird seinem Ziel-Fenster-Objekt gemeldet. Es kann von einer Operation der zugehörigen Fensterklasse bearbeitet, an eine Komponente delegiert oder an eine Oberklasse weitergeleitet werden. • Weitergeleitete Ereignisse werden spätesten in der Oberklasse Frame einer Standardbehandlung zugeführt. • Ereignisse können bearbeitet werden, wenn für sie ein Zuhörer (engl. Listener) angemeldet wird. Für jede Ereignis-Klasse kann man einen Zuhörer definieren, der eine vordefinierte Schnittstellen-Klasse implementieren muß.
Nachrichten-Schleife (Message Loop) • Ein interaktives Fenster-Programm besteht aus fortgesetztem Warten auf Ereignisse, Empfangen und Bearbeiten von Nachrichten. Dies findet in einer Endlos-Schleife, der sogenannten Nachrichten-Schleife (engl: Message Loop) statt. Diese folgt dem folgenden Muster: { Initialisiere_Dich; do { Empfange und bearbeite das naechste Ereignis;} while (Nicht Fertig); Raeume Auf; } Message Loop
Zuhörer für Ereignis-Klassen Für verschiedene Klassen von Ereignissen werden Zuhörer-(Schnittstellen-) Klassen definiert. Beispiele solcher Definitionen finden sich für: ComponentListener: behandelt alle Ereignisse, die eine Komponente betreffen. Diese sind: Sichtbarmachen, Verstecken, Bewegen, Vergrößern und Verkleinern der Komponente. ContainerListener: fügt Komponenten zu einem Container hinzu bzw. entfernt solche. KeyListener: behandelt Ereignisse beim Arbeiten mit der Tastatur. MouseListener: behandelt Maus-Ereignisse WindowListener: öffnet und schließt, ikonisiert und de-ikonisiert, aktiviert und de-aktiviert Fenster. ActionListener: behandelt das Aktivieren bzw. Auswählen einer Komponente.Dazu gehören das Betätigen von Bedienknöpfen, die Auswahl von Menüeinträgen etc.
Adapter-Klassen • Die meisten dieser Ereignis-Klassen beinhalten mehrere einzelne Ereignisse die (möglicherweise verschieden) behandelt werden sollen. • Für diese sind besondere Adapter-Klassen definiert, die alle in der Schnittstelle festgelegten Ereignisse mit leeren Operationen implementieren. • Der Sinn dieser Adapter besteht darin, die Bildung eigener Unterklassen zu ermöglichen, in denen einige dieser Ereignisse spezifisch behandelt werden können - ohne daß eine Behandlung aller Ereignisse angegeben werden muß. • Die Operation addWindowListener (ererbt von der Klasse Frame) stellt den Bezug zu der selbstdefinierten Zuhörer-Klasse MeinWindowListener her. • Im Gegensatz zu dem ersten Beispielprogramm in diesem Abschnitt kann die nächste Version des Programms jetzt mit normalen Mitteln beendet werden: Wenn das Kästchen zum Schließen des aktiven Fensters angeklickt wird, wird das Ereignis windowClosing ausgelöst, der Zuhörer wird aktiviert und beendet das gesamte Programm mit Hilfe der Methode exit der Klasse System.
Ereignisbehandlung (1) Ein typisches Ereignis ist das Schließen eines aktiven Fensters. import java.awt.*; import java.awt.event.*; class MeinWindowListener extends WindowAdapter{ public void windowClosing(WindowEventevent){ System.exit(0); // Fenster schliessen u. beenden} } class Fenster extends Frame {Fenster() { super("Fenster zum Hof");addWindowListener(new MeinWindowListener()); setSize(800, 600); setVisible(true); }}
Ereignisbehandlung (2) • Das Schließen des Fensters wird durch eine plattformabhängige Konvention zum Anklicken eines Kästchens im Rahmen des Fensters ausgelöst. • Dieses Ereignis wird von der virtuellen Java Maschine erkannt und in ein plattformunabhängiges EreigniswindowClosing umgesetzt. • Wir könnten auch einen AWT-typischen Bedienknopf vorsehen, der das Fenster schließt und das Programm beendet. • Die Operation fensterBeendenzum expliziten Beenden des Fensters enthält einen Aufruf der Operation dispose, die dem Java-Interpreter Gelegenheit zum Aufräumen gibt. (vgl. nächste Folie)
Ereignisbehandlung (3) import java.awt.*; import java.awt.event.*; class Fenster extends Frame {Fenster() { super("Fenster zum Hof"); addWindowListener(new WindowAdapter() {// s.unten (*) public void windowClosing(WindowEvent e) { fensterBeenden(); } }); setBackground(Color.lightGray); setSize(800, 600); setVisible(true); } void fensterBeenden() { dispose(); System.exit(0); } } (*) Hier wird das Java-Konzept der anonymen Klasse genutzt, um eine Unterklasse von WindowAdapter zu deklarieren, genau einmal zu instanziieren und anzuwenden.
Bedienknöpfe • Standard-Elemente von Fenstern sind Bedienknöpfe. Die Klasse Buttonmodelliert das Verhalten von Bedienknöpfen. • Im folgenden Beispiel fügen wir zwei Bedienknöpfe zu unserer Fensterklasse hinzu. • Der erste Bedienknopf stopKnopfsoll zum Schließen des Fensters und zum Beenden des Programms dienen. • Der zweite Bedienknopf tuwasKnopfsoll als Platzhalter für Aktionen künftiger Anwendungen dienen. Vorläufig ist als Platzhalter die Operation tuWas() vorgesehen. Diese gibt einen Text aus. • Analog zu Bedienknöpfen können Menüs definiert werden.
Beispiel mit Bedienknöpfen (1) Die Klasse Fenster erhält zwei zusätzliche Datenfelder für die Bedienknöpfe. import java.awt.*; import java.awt.event.*; class Fenster extends Frame{ private static Button stopKnopf = new Button("Stop"); private static Button tuWasKnopf = new Button("TuWas"); Fenster() { super("Fenster zum Hof"); setLayout(new FlowLayout()); ... • Bedienknöpfe und andere Komponenten können einem Fenster auf verschiedene Weise hinzugefügt werden. • Zu diesem Zweck gibt es den Layout-Manager. Wir wählen Flow-Layout als einfachste Möglichkeit, das Fenster zu verwalten. • Die Komponenten werden dabei der Reihe nach in ihrer aktuellen Größe dem aktuellen Fenster hinzugefügt. • Dabei versucht der Layout-Manager, von oben nach unten zeilenweise Platz für die Komponenten zu finden. In den jeweiligen Zeilen werden so viele Komponenten wie möglich mittig zentriert angeordnet.
Die Bedienknöpfe werden konstruiert: Beispiel mit Bedienknöpfen (2) StopButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { FensterBeenden(); } }); add(StopButton); TuWasButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { TuWas(); } }); add(TuWasButton); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { FensterBeenden(); } }); setBackground(Color.lightGray); setSize(800, 600); setVisible(true); }
Beispiel mit Bedienknöpfen (3) • Nunmehr wird nur noch die Platzhalter-Routine tuWas hinzugefügt. • Diese gibt eine Zeichenkette in der Farbe rotan den Koordinaten x=100 und y=250 aus. void tuWas(){ Graphics g = getGraphics(); g.setColor(Color.red); g.drawString("Tu was", 100, 250); } • Für eine konkrete Anwendung läßt sich nun die Operation TuWas durch eine beliebige gewünschte Routine ersetzen. • Damit kann man etwa die Beispiele aus Kap. 9 mit einer graphischen Benutzer-Schnittstelle versehen.
Grafikausgabe in Fenstern • Um Grafik in einem Fenster auszugeben, benötigt man einen Graphics Context für das Fenster. • In diesem sind alle wichtigen Graphik-Eigenschaften zusammengefaßt. Diese sind unabhängig von spezifischen Geräten definiert. • Die Operation getGraphics liefert zu einem gegebenen Fenster einen Graphics-Context. Mit diesem können dann Graphik-Funktionen ausgeführt werden. • Die elementaren Eigenschaften sind in der Definition der abstrakten Klasse Graphics zusammengefasst. • Weitergehende Operationen findet man in der Unterklasse Graphics2D. java.lang.Object java.awt.Graphics java.awt.Graphics2D
Graphische Operationen (1) Die einfachsten Operationen der Klasse Graphics sind: drawLine (int x1, int y1, int x2, int y2)Zeichnet eine Linie von dem Punkt (x1,y1) zu dem Punkt (x2,y2). drawPolygon (int[] xPoints, int[] yPoints, int n)Erzeugt einen Polygonzug mit n Punkten. drawPolygon (Polygon p)Wie oben, aber mit einem Parameter vom Typ Polygon. drawRect (int x, int y, int w, int h)Malt ein Rechteck ausgehend von dem Punkt (x,y) mit der Breite w und der Höhe h. Varianten sind: draw3DRect, drawRoundRect,fillRect, fill3DRectundfillRoundRect. drawOval (int x, int y, int w, int h)Malt eine Ellipse bzw. einen Kreis in einem Rechteck. Dieses ist wie bei drawRect definiert. Varianten sind: drawArc, fillArcundfillOval.
Grafische Operationen (2) drawString (String str, int x, int y)Gibt einen String aus. Anfangsposition und Basislinie sind durch den Punkt (x,y) definiert. setColor(Color c)Setzt die Malfarbe. In der Klasse Color findet man Konstanten und Operationen für Farben. clearRect (int X, int Y, int W, int H)Löscht ein Rechteck. Diese Funktion bewirkt, daß die Malfarbe temporär auf die Hintergrundfarbe eingestellt und dann fillRect(x, y, w, h) ausgeführt wird. setFont (Font f)Setzt den Zeichensatz für die String-Ausgabe. In der Klasse Font findet man Konstanten und Operationen für Fonts.
Beispiel Graphik-Routinen (1) Eine Erweiterung der Operation tuWas des Fensterbeispiels demonstriert die Verwendung der Graphik-Ausgabe: void tuWas(){ Font font = new Font("Helvetica", Font.BOLD, 36); Graphics g = getGraphics(); g.setColor(Color.pink); g.setFont(font); g.drawString("Kilroy was here...", 10, 150); g.setColor(Color.red); g.fillOval(200, 200, 200, 150); g.setColor(Color.black); for (int i = 150; i >= 5; i -= 10) g.drawOval(200, 200, i + 50, i); }
Beispiel Graphik-Routinen (2) • Die aktuelle Fenstergrösse bestimmen wir mit der Funktion getSize(). • Daneben gibt es: getMinimumSize(), getMaximumSize() und getPreferredSize(). String ts(Dimension d){ return " W= "+d.width + " "+d.height;} void tuWas(){ Font font = new Font("Helvetica", Font.BOLD, 20); Graphics g = getGraphics(); g.setFont(font); String s1 = "Minimum Size: " + ts(getMinimumSize()); String s2 = "Maximum Size: " + ts(getMaximumSize()); String s3 = "Preferred Size: " + ts(getPreferredSize()); String s4 = "Actual Size: " + ts(getSize());; g.setColor(Color.blue); g.drawString(s1, 10, 50); g.setColor(Color.red); g.drawString(s2, 10, 150); g.setColor(Color.green); g.drawString(s3, 10, 250); g.setColor(Color.black); g.drawString(s4, 10, 350); }
Maus-Ereignisse (1) • Für die Bearbeitung von Maus-Ereignissen gibt es zwei vordefinierte Schnittstellen-Klassen. • Man kann auf Mausereignisse reagieren, wenn man eine Zuhörer-Klasse schreibt, die eine oder beide dieser Schnittstellen-Klassen implementiert. • Man kann aber auch eine Unterklasse von MouseAdapter oder MouseMotionAdapter definieren und ggf. nur einige der Ereignisse behandeln. • Wegen der von AWT angestrebten Plattform-Unabhängigkeit wird generell nur ein Mausknopf berücksichtigt. • Zwischen linkem und anderen Mausknöpfen wird ebenfalls nicht unterschieden.
Maus-Ereignisse (2) • Operationen zum Behandeln von Mausereignissen haben einen Parameter vom Typ MouseEvent. • Diese Klasse stellt Operationen zur Verfügung, um festzustellen, wo das Ereignis stattfand, wie häufig ein Klick stattfand etc. Diese Operationen sind: getPoint bzw. getX und getY bzw. getClickCount usw. • In der Schnittstelle MouseListener finden sich die folgenden Ereignisse: • mouseClicked (MouseEvent event) • mouseEntered (MouseEvent event) • mouseExited (MouseEvent event) • mousePressed (MouseEvent event) • mouseReleased (MouseEvent event)
Maus-Ereignisse (3) • In der Schnittstelle MouseMotionListener finden sich die folgenden Ereignisse: • mouseMoved (MouseEvent event) • mouseDragged (MouseEvent event). • Das folgende Beispiel zeigt, wie man Maus-Ereignisse nutzen kann. • Das Programm hat außer dem Stop-Button drei weitere Knöpfe erhalten. Mit diesen kann man den Wunsch signalisieren, Linien, Rechtecke und Ellipsen zu malen. • Jedesmal, wenn ein Mausknopf gedrückt wird, merkt es sich die Position. Wenn der Mausknopf wieder losgelassen wird, ermittelt es die neue Position und malt eine der drei Zeichnungsarten, je nachdem, welcher Knopf zuletzt betätigt wurde.
Beispiel mit der Maus (1) Die Klasse Fenster erhält Bedienknöpfe für die gewünschten Zeichnungen. import java.awt.*; import java.awt.event.*; class Fenster extends Frame{ private static Button stopKnopf = new Button("Stop"); private static Button linienKnopf= new Button("Linien malen"); private static Button rechteckKnopf = new Button("Rechtecke malen"); private static Button kreisKnopf = new Button("Kreise malen"); private int zeichenModus = 1; private int x1; private int y1; x1 und y1 werden benötigt, um die jeweils letzte Mausposition zu speichern.
Beispiel mit der Maus (2) Die Bedienknöpfe werden dem Fenster als Komponenten hinzugefügt: linienKnopf.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { zeichenModus = 1; } }); add(linienKnopf); // usw. für Kreise und Rechtecke
Beispiel mit der Maus (3) • Beim EreignismousePressed merken wir uns die Mausposition (x1,y1). • Beim EreignismouseReleased merken wir uns die Mausposition (x2,y2) und malen mit diesen Punkten die gewünschte Figur. addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e){ x1 = e.getX(); y1 = e.getY(); } public void mouseReleased(MouseEvent e){ int x2 = e.getX(); int y2 = e.getY(); Graphics g = getGraphics(); g.setColor(Color.blue); if (zeichenModus == 1) g.drawLine(x1, y1, x2, y2); else { int w = Math.abs(x1 - x2); int h = Math.abs(y1 - y2); int x = Math.min(x1, x2); int y = Math.min(y1, y2); if (zeichenModus == 2) g.drawRect(x, y, w, h); else if (zeichenModus == 3) g.drawOval(x, y, w, h); }}});
Paint • Das letzte Beispiel hat einen gravierenden Nachteil: • Man kann zwar grafische Objekte malen - aber wenn man das Fenster vergrößert oder verkleinert, verschwinden diese wieder. • Man kann dies vermeiden, wenn man die vordefinierte Operation paint überschreibt. • paint wird genau dann aufgerufen, wenn das aktuelle Fenster neu gemalt wird. Dies ist z.B. der Fall, wenn das Fenster vergrößert oder verkleinert wird. Für das, was geschehen soll, wenn ein Fenster neu gezeichnet wird, ist der Programmierer selbst verantwortlich. Er muß passenden Code in der Operation paint hinterlegen. Diese ist wie folgt definiert: public void paint(Graphics g) { ... } • Beim letzten Beispiel muß man einfach eine Liste der bisher erzeugten grafischen Objekte anlegen und diese in der Operation paint neu malen.
Beispiel mit Paint (1) • Um die graphischen Objekte in der Methode paint erneut zeichnen zu können, müssen wir sie zwischenspeichern. • Es bietet sich an, hierfür eine Liste zu verwenden. • Wir nehmen nunmehr an, wir hätten eine passende Klasse für diese Liste und eine Operation draw dieser Klasse, die graphische Objekte malen kann. • Dann können wir die Operation paint vervollständigen: public void paint(Graphics g) { g.setColor(Color.red); for (GeoListe gl = anfang; gl != null; gl = gl.nf) gl.el.draw(g); } • Für die Definition der Klasse GeoListe vgl. unten.
Beispiel mit Paint (2) Nunmehr können wir darangehen, geeignete Klassen für die Liste graphischer Objekte zu definieren: class GeoKlasse{ int xx1, yy1, xx2, yy2; int x, y, w, h; int zeichenModus; GeoKlasse(int z, int x1, int y1, int x2, int y2){ zeichenModus = z; xx1 = x1; yy1 = y1; xx2 = x2; yy2 = y2; w = Math.abs(xx1 - xx2); h = Math.abs(yy1 - yy2); x = Math.min(xx1, xx2); y = Math.min(yy1, yy2); } void draw(Graphics g){ if (zeichenModus == 1) g.drawLine(xx1, yy1, xx2, yy2); else if (zeichenModus == 2) g.drawRect(x, y, w, h); else if (zeichenModus == 3) g.drawOval(x, y, w, h); } }
Beispiel mit Paint (3) • Wir brauchen noch eine Klasse für eine Liste grafischer Objekte: class GeoListe{ GeoKlasse el; GeoListe nf; GeoListe(GeoKlasse e){el = e; nf = null;} GeoListe(GeoKlasse e, GeoListe n){el = e; nf =n;} } • Zusätzlich benötigen wir Felder, um Anfang und Ende der Liste graphischer Objekte zu speichern. • Außerdem benötigen wir eine Operation, die ein Objekt in diese Liste einhängt. private GeoListe anfang, ende; void addGeoObj(GeoKlasse o){ GeoListe gl = new GeoListe(o); if (anfang == null) ende = anfang = gl; else {ende.nf = gl;ende = gl;} }
Beispiel mit Paint (4) • Die Operation addMouseListener des Beispiels, die als einzige geändert werden muß, wird sogar einfacher, da wir die Arbeit des Normalisierens der Koordinaten in den Konstruktor von GeoKlasse verlegt haben: addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e){ x1 = e.getX(); y1 = e.getY(); } public void mouseReleased(MouseEvent e){ int x2 = e.getX(); int y2 = e.getY(); Graphics g = getGraphics(); g.setColor(Color.blue); GeoKlasse o = new GeoKlasse(ZeichenModus,x1,y1,x2,y2); o.draw(g); addGeoObj(o); } });
Weitere Bedienelemente von Programmen und Fenstern • Von besonderem Interesse ist die Gestaltung der Benutzerschnittstelle eines Programms. • Zu diesem Zweck kann man mit folgenden typischen Bedienelementen operieren: • Die Menüs sind das Standardhilfsmittel, um Befehle und Optionen bereitzustellen. Sie können an einer Menüleiste befestigt sein, oder als Popup-Menü per Mausklick aktiviert werden. • Bedienknöpfe können an beliebiger Stelle in einem Fenster installiert werden. Sie haben eine Inschrift und werden durch Anklicken aktiviert. • Dialogboxen bieten die Möglichkeit, Eingaben an Programme zu machen. Sie sind aus Elementen wie Check-Boxen, List-Boxen, Eingabefeldern etc. zusammengesetzt. • Werkzeugleisten (toolbars) bieten häufig benutzte Befehle und Abkürzungen für ganze Befehlssequenzen.
Java-Anwendungen, Applets • Java kennt drei Arten von Anwendungen: • Konsol-Anwendungen. • Anwendungen. • Applets. • Wir haben bisher ausschließlich Konsol-Anwendungen betrachtet: ohne Fenster, Interaktion nur per Kommandozeile und mit den I/O-Routinen von System. • Anwendungensind die uns (z.B. von Windows) bekannten interaktiven Programme mit Fenster und Benutzer-Interaktion. • Ein Applet ist ein (i.a. kleines) Anwendungsprogramm, das direkt aus einer HTML-Seite heraus gestartet werden kann. • Applets werden z.B. für Animationen im Text, zur Simulation von Algorithmen und Visualisierung von Aktivitäten und Vorgängen genutzt. • Die ursprüngliche Idee, auch komplexe Anwendungen (wie z.B. Textverarbeitung) als Applet zu implementieren, hat sich bislang nicht durchgesetzt.
Applets • Das zu einem Applet zugehörige Programm muß von der Klasse Applet abgeleitet sein. • Applets können alle typischen Fenster- und Grafikaktivitäten entfalten. • Das folgende Beispiel zeigt den Einbau eines Applets in eine HTML-Seite: <HTML> <HEAD> <TITLE> Ein einfaches Applet </TITLE> </HEAD> <BODY> Hallo-Welt-Applet <P> <APPLET CODE="Applet1.class" WIDTH=400 HEIGHT=200> </APPLET> </BODY> </HTML>
Beispiel: Applet 1 • Ein Applet wird als Erweiterung der Klasse Applet definiert. • Dabei müssen die Methoden init und paintdefiniert werden. import java.awt.*; import java.applet.*; public class Applet1 extends Applet { static final String Gruss = "Hallo Welt"; private Font font; public void init() { super.init(); font = new Font("Helvetica", Font.BOLD, 48); } public void paint(Graphics g) { // nächste Folie } }
Beispiel: Applet 1 - paint • Im Prinzip kann eine beliebige paint-Operation genommen werden. Z.B. die folgende: public void paint(Graphics g) { g.setColor(Color.pink); g.fillOval(10, 10, 330, 100); g.setColor(Color.red); g.drawOval(10,10, 330, 100); g.drawOval(9, 9, 332, 102); g.drawOval(8, 8, 334, 104); g.drawOval(7, 7, 336, 106); g.setColor(Color.black); g.setFont(font); g.drawString(message, 40, 75); } Male eine Ellipse in der Farbe pink Weitere 4 Ellipsen, um dicke Linien zu emulieren. Ein Text.
Parameter • Auf der HTML-Seite können Parameter spezifiziert sein, z.B: <P> <APPLET code="Animator.class" width=50 height=50> <PARAM name="Verzeichnis" value="images/circle"> <PARAM name="AnzahlBilder" value="20"> </APPLET> • Auf diese Parameter kann man in der Applet-Klasse zugreifen, z.B so: String VerzeichnisStr = this.getParameter("Verzeichnis"); String AnzahlBilderStr = this.getParameter("AnzahlBilder"); int AnzahlBilder; try { AnzahlBilder = Integer.parseInt(AnzahlBilderStr);} catch (NumberFormatException e) { AnzahlBilder = 0; } for(int i = 0; i < AnzahlBilder ; i++) { ... }
Klassen-Hierarchie für Applet Object Ein Applet wird aus Klassen des awt-Pakets abgeleitet - und erhält damit eine Grafikschnittstelle. .... Component .... Container .... Panel .... Applet
Einige Operationen von Applets public boolean isActive() ; public URL getDocumentBase() ; public URL getCodeBase(); public Locale getLocale(); public String getParameter(String name) ; public AppletContext getAppletContext() ; public void resize(int width, int height) ; public void resize(Dimension d); public void showStatus(String msg); public Image getImage(URL url) ; public Image getImage(URL url, String name) ; public AudioClip getAudioClip(URL url) ; public AudioClip getAudioClip(URL url, String name) ; public String getAppletInfo() ; public String[][] getParameterInfo() ; public void play(URL url) ; public void play(URL url, String name) ; public void init() ; public void start(); public void stop() ; public void destroy();