© APSIS GmbH |
Seite 279
Seite 280
Seite 281
import java.awt.*; // (13.1) public class AWTdemo extends Frame { public AWTdemo() { super("AWT Demo"); // eigene Titelleiste ... // wird später ergänzt } }
static AWTdemo grundfenster; // Referenz fürs Hauptprogramm public static void main (String[] args) { grundfenster = new AWTdemo(); grundfenster.fensterAufbauen(); }
public void fensterAufbauen() { Label beschriftung = new Label ("Popup-Menü auf Knopfdruck"); // ¬ grundfenster.add(beschriftung); // ¬ Button knopf = new Button("Popper"); // ¬ knopf.setForeground(Color.black); knopf.setBackground(Color.yellow); grundfenster.add(knopf); // ¬ fensterMenue = new PopupMenu(); // ¬ MenuItem m1 = new MenuItem("maximieren"); MenuItem m2 = new MenuItem("minimieren"); MenuItem m3 = new MenuItem("schließen"); MenuItem m4 = new MenuItem("drucken"); fensterMenue.add(m1); fensterMenue.add(m2); fensterMenue.add(m3); fensterMenue.add(m4); grundfenster.add(fensterMenue); // ¬ grundfenster.pack(); // die Komponenten anordnen grundfenster.show(); // das Fenster sichtbar machen }
Seite 282
grundfenster.add(BorderLayout.NORTH, beschriftung); // Label grundfenster.add(BorderLayout.SOUTH, knopf); // Button
grundfenster.add(fensterMenue); // PopupMenu
grundfenster.setLayout(new FlowLayout());
Panel knopffeld = new Panel(); knopffeld.setLayout(new BorderLayout()); Button maxknopf = new Button("Maximieren"); Button minknopf = new Button("Minimieren"); Button schliessknopf = new Button("Schließen"); Button druckknopf = new Button("Drucken"); knopffeld.add(BorderLayout.WEST, maxknopf); knopffeld.add(BorderLayout.EAST, minknopf); knopffeld.add(BorderLayout.NORTH, druckknopf); knopffeld.add(BorderLayout.SOUTH, schliessknopf);
Übung 13.1: Testen Sie das Programm (13.1) auf Seite 281 mit verschiedenen Anordnungen. Fassen Sie auch die Beschriftung und den "Popper"-Knopf zu einem eigenen Panel zusammen.
Seite 283
knopf.addActionListener(new java.awt.event.ActionListener() { // (13.2) // anonymer Lauscher public void actionPerformed(ActionEvent e) { fensterMenue.show(grundfenster, 200, 75); // Popup-Menü aufklappen } });
Ereignistyp | Von processEvent gerufene Methode |
ActionEvent | ProcessActionEvent |
MouseEvent | ProcessMouseEvent ProcessMouseMotionEvent |
FocusEvent | ProcessFocusEvent |
... | ... |
Abb. 13.1: Ereignisse
grundfenster.enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.WINDOW_EVENT_MASK); // oder-Verknüpfung zweier Ereignistypmasken
public void processMouseEvent(MouseEvent e) { if (e.isPopupTrigger()) { // rechte Maustaste ¬ fensterMenue.show(grundfenster, e.getX(), e.getY()); // x- und y-Koordinaten der Mausposition e.consume(); // fertig bearbeitet, nicht weiterreichen } } public void processWindowEvent(WindowEvent e) { if (e.getID()== WindowEvent.WINDOW_CLOSING) System.exit(0); }
public void fensterAufbauen() { Lauscher lauscher = new Lauscher(); // Lauscherobjekt(e) erzeugen Panel knopffeld = new Panel(); // Knopffeld ... // vier Knöpfe erzeugen // Standard-Ereignisbehandlung mit Lauscherobjekt(en) maxknopf.addActionListener(lauscher); // der Universallauscher minknopf.addActionListener(lauscher); schliessknopf.addActionListener(lauscher); druckknopf.addActionListener(lauscher); grundfenster.add(knopffeld); // Popup-Menü fensterMenue = new PopupMenu("fenster"); ... // vier Menüfelder erzeugen // Standard-Ereignisbehandlung, gleiches Lauscherobjekt wie oben: m1.addActionListener(lauscher); // der Universallauscher m2.addActionListener(lauscher); m3.addActionListener(lauscher); m4.addActionListener(lauscher); grundfenster.add(fensterMenue); ... }
class Lauscher implements ActionListener { public void actionPerformed(ActionEvent e) { String kommando = e.getActionCommand(); if (kommando.equalsIgnoreCase("Maximieren")) // "maximieren" gleich "Maximieren" grundfenster.maximieren(); else if (kommando.equalsIgnoreCase("Minimieren")) grundfenster.minimieren(); else if (kommando.equalsIgnoreCase("Drucken")) grundfenster.bildschirmabzug(); else if (kommando.equalsIgnoreCase("Schließen")) grundfenster.schliessen(); } }
Übung 13.2: Realisieren Sie das "saubere" objektorientierte Lauscherkonzept für das Programm (13.2) auf Seite 283: Implementieren Sie für jedes der o.g. Ereignisse einen eigenen Lauscher; die Abfrage auf die Art des Kommandos entfällt dann. Beachten Sie: Nur vier verschiedene Lauscher müssen erzeugt werden, da den unterschiedlichen Maximierungsereignissen dasselbe Lauscherobjekt zugeordnet werden kann, ebenso für Minimierung, usw.
Übung 13.3: Lösen Sie nun im Programm (13.2) auf Seite 283 die Aktionen mit Hilfe des vereinfachten Ereignismodells (d.h. über processActionEvent) aus.
Seite 285
public void paint(Graphics grafik) { // (13.3) grafik.setFont(new Font("Helvetica", Font.BOLD, 30)); grafik.setColor(Color.cyan.darker()); grafik.drawString("Man kann im Grundfenster malen", 40, 40); // y groß genug wählen, damit die Schrift nicht oben aus dem Fenster verschwindet }
// Zeichenfläche definieren und paint-Methode überschreiben: class Atelier extends Canvas { public void paint(Graphics grafik) { grafik.setFont(new Font("Helvetica", Font.BOLD, 20)); grafik.setColor(Color.blue); grafik.drawString("Man kann in der Zeichenfläche malen", 5, 25); } } // Zeichenfläche anlegen, formatieren und einbinden: zeichenflaeche = new Atelier(); zeichenflaeche.setSize(500, 270); zeichenflaeche.setBackground(Color.lightGray); // hebt die Zeichenfläche vom Grundfenster ab (zu Testzwecken) grundfenster.add(zeichenflaeche);
public void paint(Graphics grafik) { grafik.setFont(new Font("Helvetica", Font.BOLD, 30)); grafik.drawString("Man kann im Grundfenster malen", 40, 430); zeichenflaeche.getGraphics().drawString( "... oder vom Grundfenster aus in die Zeichenflaeche hineinmalen", 25, 40); //... }
try { // (13.4) Image meinBild = this.createImage((java.awt.image.ImageProducer) (new URL("file:/laufwerk:/[Pfad]/balloons.gif").getContent())); grafik.drawImage(meinBild, 5,40, this); // y groß genug, sonst unsichtbar ¬ } catch (MalformedURLException e) { System.err.println(e); } catch (IOException e) { System.err.println(e); }
try { Image meinBild = werkzeugkiste.getImage( new URL("file:/laufwerk:/[Pfad]/balloons.gif")); grafik.drawImage(meinBild, 5,40, this); // y groß genug wählen, sonst unsichtbar ¬ } catch (MalformedURLException e) { System.err.println(e); }
Übung 13.4: drawImage gibt es auch mit zwei weiteren int-Parametern, die die Wiedergabegröße des Bildes festlegen. Ein Bild lässt sich dadurch vergrößern, verkleinern, stauchen und strecken.
grafik.drawImage(bild, 5, 40, bild.getWidth(this), bild.getHeight(this), this);
ist gleich bedeutend mit der markierten Zeile des Programm (13.4) auf Seite 286. Suchen Sie sich ein schönes Bild (z.B. ein Foto) und versuchen Sie eine primitive Animation nach folgendem Muster:
final int BREITE = 100; // (13.5) final int HOEHE = 100; final int VERZOEGERUNG = 20000; Image bild; ... public void init() { bild = ... }; // Image-Objekt erzeugen public void paint(Graphics g) { for (int i = 0; i < 300; i++) { g.drawImage(bild, x, y, BREITE + i, HOEHE, this); Thread.sleep(VERZOEGERUNG); // kleine Pause g.clearRect(x, y, BREITE + i, HOEHE); // wieder löschen } repaint(); // und wieder von vorne }
Seite 287
PrintJob ausdruck = this.getToolkit().getPrintJob(this, "Hardcopy", // (13.6) einstellungen);
if (ausdruck == null) return; // oder NullPointerException abfangen
private void bildschirmabzug(){ java.util.Properties druckereinstellung = null; // Compiler fordert Initialisierung PrintJob ausdruck = werkzeugkiste.getPrintJob(this, "Hardcopy", druckereinstellung); // Benutzer setzt Druckereinstellungen im Dialog if (ausdruck == null) return; // Benutzer hat "Abbrechen" gewählt Graphics druckbild = ausdruck.getGraphics(); this.print(druckbild); // this ist ein Frame-Objekt druckbild.dispose(); // Druckseite beenden und zum Drucker schicken ausdruck.end(); // Druckjob beenden }
Seite 288
Seite 288
public void iterator(final String rueckruf) { // (13.7) try { Knoten knoten = anfang; while (knoten != null) { Object ziel = knoten.wert; // der im Knoten gespeicherte Wert ist Zielobjekt Class klasse = ziel.getClass(); // Klasse des Zielobjekts ¬ java.lang.reflect.Method methode = klasse.getMethod( // ¬ rueckruf, new Class[0]); // gesuchte Methode methode.invoke(ziel, new Object[0]); // Aufruf der gefundenen Methode ¬ knoten = knoten.vorwaerts; // zum nächsten Knoten gehen } } catch (Exception ausnahme) { System.err.println("Rueckruf: " + ausnahme); } }
public Object invoke(Object obj, Object args[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
knoten.wert.getClass().getMethod(methode, new Class[0]).invoke( knoten.wert, new Object[0]);
Seite 290
private String namenErmitteln() { // (13.8) return getClass().getFields()[knoten.pos].getName(); // ¬ } private void setzen(final Knoten knoten) { // wie im Programm (9.15) versprochen Aufz ref = ersterAkt; for (int i = 0; i <= knoten.pos; i++) { ref.knoten.letzter = letzterAkt; ref = ref.knoten.naechster; } }
public Field[] getFields() throws SecurityException; // ungeprüft
public static final Farbe BLAU = new Farbe();
Übung 13.5: Zeigen Sie, dass Reflexion polymorph ist: Rufen Sie eine Oberklassenmethode auf, die alle Felder und Methoden über getName anzeigt. Sie sind durch
public java.lang.reflect.Method[] getMethods() throws SecurityException
erhältlich. Sie erhalten auch die Unterklassenkomponenten. Sie können dabei auch beobachten, welche Komponenten von Object immer vererbt werden.
Seite 291
import java.io.*; // (13.9) public class Menuegenerator { private InputStream tastatur = System.in; private PrintStream konsole = System.out; private String tastaturEingabe(String dialogtext) throws IOException { konsole.println(dialogtext); StringBuffer puffer = new StringBuffer(); // zum Sammeln der Eingabezeichen int zeichen = tastatur.read(); // Byte-Eingaben als int-Werte while ((char)zeichen != '\n' && (char)zeichen != '\r' ) { // bis zum Zeilenende puffer.append((char) zeichen); zeichen = tastatur.read(); } zeichen = tastatur.read(); return puffer.toString(); } ...
import java.io.*; public class Menuegenerator { ... private FileWriter zieldatei; // wird mit der Ausgabedatei verbunden private PrintWriter ausgabe; // zur zeilenweisen Ausgabe in die Zieldatei private static void dateiUndKlassennamenSetzen() throws IOException { eingabe = tastaturEingabe ("Wie soll die Menüklasse heißen?"); zieldatei = new FileOutputStream(eingabe + ".java"); ausgabe = new PrintWriter(zieldatei, true); ausgabe.print("// Abstrakte Menüklasse " + eingabe + "\r\n"); ausgabe.print("// erzeugt vom Menügenerator" + "\r\n" + "\r\n"); ausgabe.print("import lehrbuch.Anim;" + "\r\n\r\n"); ausgabe.print("abstract public class " + eingabe + " extends java.applet.Applet {"); ausgabe.print("\r\n"); } ... }
import java.io.*; public class Menuegenerator { ... private FileReader schablone; private BufferedReader textbausteine; // zur zeilenweisen Eingabe static { try { schablone = new FileReader("MenueSchablone.txt"); } catch (FileNotFoundException e) { System.err.println("Datei 'MenueSchablone.txt' nicht auffindbar" + e); System.exit(-1); // Programmabbruch mit Fehlercode -1 } textbausteine = new BufferedReader(schablone); } private void kopierenBisXXX throws IOException { eingabe = textbausteine.readLine(); // zeilenweise Eingabe while (! eingabe.startsWith("XXX")) { // Endekriterium Textbaustein ausgabe.println(eingabe); // zeilenweise Ausgabe eingabe = textbausteine.readLine(); } }
import java.io.*; // (13.10) public class SeqDateiImpl implements SeqDatei { private boolean lesemodus; private Object aktuellesObjekt; private String dateiname; private ObjectInputStream eingabe; // ¬ private ObjectOutputStream ausgabe; // ¬ public SeqDateiImpl (String file) { // Konstruktor, setzt den Dateinamen dateiname = file; } public void neuBeschreiben() { // setzt Schreibmodus, setzt auf Anfang lesemodus = false; try { ausgabe = new ObjectOutputStream(new FileOutputStream(dateiname)); // ¬ } catch (IOException e) { throw new DateiFehler(); } } public void zuruecksetzen() { // setzt Lesemodus + Anfang lesemodus = true; ... } public void eintragen(final Object element) throws LesemodusFehler { if (lesemodus) throw new LesemodusFehler(); else try { ausgabe.writeObject(element); // ¬ } catch (IOException e) { throw new DateiFehler(); } } public void naechstesElement() throws SchreibmodusFehler, DateiendeAusn { if (!lesemodus) throw new SchreibmodusFehler(); else try { aktuellesObjekt = eingabe.readObject(); // ¬ } catch (EOFException eof) { throw new DateiendeAusn(); } catch (Exception e) { throw new DateiFehler(); } } public Object aktuellesElement() throws SchreibmodusFehler, DateiendeAusn { ... return aktuellesObjekt; } ... }
class Getraenk implements java.io.Serializable { ... } // (13.11) class Eimer implements java.io.Serializable { ... } ... Eimer eimer = new Eimer(); SeqDatei datei = new SeqDateiImpl("Eimer.dat"); datei.neuBeschreiben(); datei.eintragen(eimer); ...
Übung 13.6: Schreiben Sie ohne Verwendung der Klasse SeqDateiImpl ein Programm, das menügesteuert Eimer, Kreise und Farben in einen polymorphen Datenbehälter einträgt und diesen als ganzes Objekt in eine Datei ausgibt. Schreiben Sie ein zweites Programm, das die Datei liest und den Inhalt des Datenbehälters anzeigt.
Seite 294
Seite 295
Seite 295
public void init(); public void start(); public void stop(); public void paint(Graphics g); // geerbt von java.awt.Panel
<APPLET CODE="HalloWelt.class" WIDTH=450 HEIGHT=100 > </APPLET>
appletviewer Klasse.html
Abb. 13.2: Interpretieren mit appletviewer
getImage // zum Erzeugen von Bildobjekten aus .gif oder .jpeg-Dateien getAudioClip // zum Erzeugen von Audioobjekten aus .au oder .wav play // zum Abspielen von Audioobjekten
getCodeBase // ermittelt den Pfad bis zur aktuellen Applet-Datei getDocumentBase // ermittelt den Pfad bis zur aktuellen HTML-Datei getAppletContext // macht Kontextinformationen des Stöberers zugänglich
Übung 13.7: Suchen Sie sich eins ihrer Übungsprogramme heraus, das Sie mit av ausgeführt haben. Schreiben Sie nun die erforderliche Applet-Klausel selbst und rufen Sie das Programm direkt mit dem appletviewer auf.
Seite 297
<APPLET CODEBASE=http://www.tfh-berlin.de/~oo-plug/Java CODE=tfhLogo.class, WIDTH=200, HEIGHT=100>
Seite 297
Protokoll://Host[:Port]/Pfad/Dateiname[#interneReferenz]
http://www.tfh-berlin.de/~oo-plug/Java/tfhLogo.gif
public URL (String url) throws MalformedURLException; public URL (String protocol, String host, String file) throws MalformedURLException; public URL (String protocol, String host, int port, String file) throws MalformedURLException;
try { // (13.12) URL u1 = new URL ("http://tfh-berlin.de/~oo-plug/Java/tfhLogo.gif"); URL u2 = new URL ("http", "tfh-berlin.de", "/~oo-plug/Java/tfhLogo.gif"); // '/' vor Dateinamen erforderlich URL u3 = new URL ("http", "tfh-berlin.de", 80, "/~oo-plug/Java/tfhLogo.gif"); } catch (MalformedURLException ausnahme) { System.err.println(ausnahme); }
(u1.sameFile(u2) && u2.sameFile(u3)) == true;
public URL (URL url, String file) throws MalformedURLException;
URL u4 = new URL (u1, "tfhLogo.gif"); URL u5 = new URL (u1, "../Ada/adaLogo.gif");
URL u6 = new URL (getDocumentBase(), "beispiel.html");
Seite 298
public final InputStream openStream() throws IOException; public URLConnection openConnection() throws IOException; public final Object getContent() throws IOException;
URL u; InputStream strom; try { u = new URL("http://www.tfh-berlin.de/~oo-plug/Java/index.html"); strom = u.openStream(); } catch (Exception ausnahme) { System.err.println(ausnahme); }
import java.net.*; // URL // (13.13) import java.io.*; // DataInputStream public class TextLaden { public static void main (String args[]) { URL url; String aktuelleZeile; DataInputStream lesestrom; if (args.length > 0) { // URL wird als Aufrufparameter erwartet System.out.println("Datei " + args[0] + ":\n"); try { url = new URL(args[0]); // throws MalformedUrlException lesestrom = new DataInputStream(url.openStream()); // throws IOException aktuelleZeile = lesestrom.readLine(); // throws IOException while (aktuelleZeile != null) { System.out.println(aktuelleZeile); aktuelleZeile = lesestrom.readLine(); // throws IOException } } catch (Exception ausnahme) { System.err.println(ausnahme); } } } }
Übung 13.8: Probieren Sie das Programm TextLaden mit der Leitseite der TFH Berlin aus (allerdings vielleicht mit einer Zählschleife, die die Zahl der ausgegebenen Zeilen beschränkt!):
java TextLaden http://www.tfh-berlin.de
oder mit sich selbst:
java TextLaden file:/[Pfad]/TextLaden.java
Seite 299
try { URL url = new URL("http://www.tfh-berlin.de"); ObjectInputStream objekt = new ObjectInputStream(url.openStream()); } catch (Exception ausnahme) { System.err.println(ausnahme); }
import java.net.*; // URL // (13.14) import java.io.*; // DataInputStream public class ObjektLaden { public static void main (String args[]) { URL url; String aktuelleZeile; DataInputStream lesestrom; if (args.length > 0) { // URL wird als Aufrufparameter erwartet try { url = new URL(args[0]); // throws MalformedUrlException Object obj = url.getContent();// throws ClassNotFoundException System.out.println("Es wurde ein " + obj.getClass().getName() + "-Objekt erzeugt"); } catch (Exception ausnahme) {System.err.println(ausnahme); } } } }
Übung 13.9: Probieren Sie, ob HTML-Dateien auf ihrem System unterstützt werden: Rufen Sie das Programm (13.14) mit der Kommandozeile
java ObjektLaden url
auf und geben Sie als Parameter url Adressen von verschiedenen Dateitypen an. Mit der Weiterentwicklung des Java-Systems sollten die ClassNotFoundException-Enttäuschungen seltener werden.
Seite 301
import java.rmi.*; // (13.15) public interface KlubListe extends Remote { public String name (int mitgliedsnummer) throws NrUngueltigAusn, RemoteException; public int mitgliedsnummer (String name) throws RemoteException; public void eintragen (String name) throws RemoteException; public void loeschen (String name, int mitgliedsnummer) throws RemoteException; }
import java.rmi.*; // (13.16) import java.rmi.server.*; import java.net.*; public class KlubListeImpl extends UnicastRemoteObject implements KlubListe { private String[] liste; public KlubListeImpl(int laenge) throws RemoteException { super(); // throws RemoteException // erforderlich, um Ausnahme auszulösen liste = new String[laenge]; } public String name(int nummer) throws NrUngueltigAusn, RemoteException { try { return liste[nummer]; } catch (IndexOutOfBoundsException ausnahme) { throw new NrUngueltigAusn (); } } ... // die weiteren Methoden aus der Schnittstelle ähnlich; main demnächst
KlubListeImpl klub = new KlubListeImpl();
public static void bind(String url, Remote r) throws RemoteException, AccesException, AlreadyBoundException, UnknownHostException; public static void rebind(String url, Remote r) throws RemoteException, AccesException, UnknownHostException; public static void unbind (String url, Remote r) throws RemoteException, AccesException, UnknownHostException, NotBoundException; public static Remote lookup(String url) throws RemoteException, AccesException, NotBoundException, UnknownHostException; public static String[] list(String url) throws RemoteException, AccessException, UnknownHostException;
Naming.rebind("rmi://ServerHost/VereinsRegister", klub);
Naming.rebind("VereinsRegister", klub); // gleich bedeutend
KlubListe c = (KlubListe)Naming.lookup("rmi://ServerHost/VereinsRegister");
System.setSecurityManager(new RMISecurityManager());
public static void main (String args[]) { System.setSecurityManager(new RMISecurityManager()); try { KlubListeImpl klub = new KlubListeImpl(); // throws RemoteException Naming.rebind("VereinsRegister", klub); // throws RemoteException, // AccessException, UnknownHostException, MalformedURLException System.out.println("Klub-Server ist bereit."); } catch (Exception ausnahme) { System.err.println(ausnahme); } }
import java.rmi.*; // (13.17) public class KlubAussenstelle { public static void main (String args[]) { System.setSecurityManager(new RMISecurityManager()); try { KlubListe liste = (KlubListe)Naming.lookup("rmi://Server/VereinsRegister"); liste.eintragen("Otto Meierlein"); // eintragen in die entfernte Liste int nummer = mitgliedsnummer("Otto Meierlein"); // erhaltene Nummer holen String eintrag = liste.name(nummer); // entfernten Eintrag lesen System.out.println("Ferneintrag: " + eintrag + " M. Nr.: " + nummer); } catch (Exception ausnahme) { System.err.println(ausnahme); } } }
rmic KlubListeImpl
start rmiregistry
java KlubListeImpl
java KlubAussenstelle
Seite 304
© APSIS GmbH |