Kap.14: APPLETS (Applet)
Kapitel-Index
14.1 Java-Applets (applet) in HTML-Dokumenten
Ein Applet ist ein innerhalb eines HTML-Texts ablaufendendes
(appliziertes) Programm mit Eingabe per Maus und/oder Textfeld.
Es wird aufgerufen mit einem Applet-fähigen Browser und ist angepasst an die Fenstertechnik der jeweiligen Benutzeroberfläche. Superklasse ist die im Paket java.applet vereinbarte Klasse
selbst direkte bzw. indirekte Subklasse der im Paket java.awt (Abstract Window Toolkit) vereinbarten Klassen Panel, Container und
Component. Die aktuelle HTML-Version, für dieses Buch 4.01, unterstützt das traditionelle applet-Element, z.B.
<applet code="MyApplet.class" width="636" height="400"></applet>
zum Aufruf eines Java-Applets, das als class-file übersetzt ist.
In künftigen HTML- und XHTML-Versionen ist für Multimedia-Anwendungen einschließlich Applets das object-Element vorgesehen. Das
code-Attribut gibt den Pfad und den Namen des Applets mit der
Endung .class an. Der Pfad kann entfallen, wenn der class-file im
aktuellen Verzeichnis steht. width-Attribut und height-Attribut
geben die Breite und Höhe der Darstellung in Pixeln an, die im
Applet abgefragt werden können,
int width=getWidth(), height=getHeight(); .
In diesem Buch wird als Breite width="636" gewählt, die Maximalbreite für Druck im Hochformat mit den verwendeten Browsern
(Mozila Firefox, Internet Explorer).
Zwischen applet-Tag und applet-EndTag können param-Tags (stets
ohne EndTag) angeben werden, z.B.
<param name="myParam" value="4711"> ,
deren value-Attributwert im Applet abgefragt werden kann, z.B.
String value=getParameter("myParam"); .
Für nicht-Applet-fähige Browser, die applet-Tag und applet-EndTag
sowie darin enthaltene param-Tags ignorieren, fügen wir zwischen
applet-Tag und applet-EndTag normalen HTML-Text ein, z.B.
der von nicht-Applet-fähigen Browsern alternativ ausgedruckt wird,
aber von Applet-fähigen Browsern ignoriert wird. Der Internet
Explorer ignoriert das Applet zunächst aus "Sicherheitsgründen",
druckt also "MyApplet" aus, stellt aber dann auf Wunsch des Benutzers "...Klicken...zulassen...Ja" das Applet dar. Nötigenfalls
muss ein Download des JRS (Java Runtime System) erfolgen (Literatur.2).
Im Gegensatz zu Applikationen, bei denen String-Text mit
main(String[] args) eingegeben und mit System.out.print(String s)
ausgegeben wird, wird in Applets String-Text mit getText() eingegeben und mit setText(s) oder mit drawString(s,x,y) ausgegeben.
Das folgende Einführungsapplet Listener enthält ein Textfeld
TextField txf, einen Knopf Button but und eine Marke Label lab.
Die graphischen Komponenten txf, but, lab müssen mit
add(txf);add(but);add(lab);
in den Container des Window-Fensters eingefügt werden, um sichtbar
gemacht zu werden. Das im Applet voreingestellte FlowLayout, d.h.
Layout in Schriftreihenfolge, stellt die graphischen Komponenten
dar in der Reihenfolge ihrer add-Einfügung von links nach rechts.
Passt eine Komponente in der Folge nicht mehr in die Fensterbreite, dann wird links unter der Komponentenfolge fortgesetzt. Die
Komponentenfolgen werden mittig in der Fensterbreite angeordnet.
Nach dem Observer/Observable-Modell (siehe Paket java.util)
beobachtet eine Schnittstelle ActionListener das Applet Listener,
das seinerseits den ActionListener und dessen Methode actionPerformed() implementiert und den ActionListener mit der Beobachtung des Knopfs but beauftragt:
but.addActionListener(this);
Wird der Knopf but gedrückt, dann "hört" der ActionListener den
Mausklick und ruft die Methode actionPerformed() auf, die den Text
aus dem Textfeld txf mit txf.getText() liest und in die Marke lab
mit lab.setText(txtf.getText()) schreibt.
Die Text-Graphik in paint(Graphics g) mit g.drawString(s,x,y)
ist nicht Layout-gesteuert, sondern (x,y)-Koordinaten-bestimmt.
Die Pixel-Koordinaten (x.y), d.h. x nach rechts und y nach unten,
bezeichnen den Anfangspunkt der Basislinie des Strings s. Layout
-Graphik "überdeckt" draw-Graphik, d.h. die mit FlowLayout ins
Fenster gesetzten Graphiken machen die an gleicher Stelle mit
drawString ins Fenster gesetzten Graphiken pixelweise unsichtbar.
//************************ Listener.java *************************
// Lauscht auf Button-Druck und kopiert dann TextField auf Label.*
// Implementiert die Methode actionPerformed aus ActionListener.*
// FlowLayout von txf,but,lab ueberdeckt g.drawString(s,x,y). *
//****************************************************************
// java.lang. O b j e c t
import java.awt.event.*;//ActionEvent'|| |||ActionListener
import java.awt.*; // Graphics'`Component||`Color
// TextComponent'||`Label|`-Font
// TextField'Container'`Button`--FlowLayout
import java.applet.Applet; // Applet'
public class Listener extends Applet implements ActionListener
{int size; // Zeilen- bzw. Zeichenhoehe
TextField txf=new TextField("TextField");
Button but=new Button ("Button");
Label lab=new Label (" L a b e l ");
public void actionPerformed(ActionEvent e) // ActionListener
{lab.setText (txf.getText()); // TextComponent
}
public void paint(Graphics g) // overrides Applet
{g.setColor (Color.RED);
for(int j=1;j<=3;j++) // 3 Zeilen
for(int i=0;i<getWidth()*2/size;i++)//width/Zchbreite
{g.drawString (""+j,i*size/2,j*size);} // Zchbreite size/2
}
public void start() // overrides Applet
{ size=getHeight()/3; // 3 Zeilen
setFont(new Font("SansSerif",Font.BOLD,size)); // Component
add (txf); // Container
add (but); // Container
add (lab); // Container
but.addActionListener(this); // this Listener
} // calls paint()
} // FlowLayout is default for Applet
//****************************************************************
Fig. 14.1.1a: Listener Darstellung
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
<!--***************** Listener.html ***************************-->
<meta http-equiv="content-type"
content="text/html;charset=ISO-8859-15" >
<title> Listener </title>
<applet code="Listener.class" width="636" height="192" >
Listener
</applet>
<!--***************** width=Hochformat height=3*size **********-->
Im folgenden Beispiel FontChoice werden Schrift-Fonts ausgewählt
mit dem Auswahl-Menu der Klasse java.awt.Choice.
//*********************** FontChoice.java ************************
// Auswahl des Schrift-Fonts *
//****************************************************************
// java.lang. Object
import static java.lang.Integer.parseInt; // ||||`Integer
import java.awt.event.*; // ItemEvent'||| ItemListener
import java.awt.*; // C o m p o n e n t'|`FlowLayout
// Choice'Label'`Container`Font
import java.applet.Applet; // `Applet'
public class FontChoice extends Applet implements ItemListener
{String[][]ITEM={{"SansSerif","Serif","MonoSpaced"},
{"BOLD+ITALIC 3","ITALIC 2","BOLD 1","PLAIN 0"},
{"SIZE 30","SIZE 24","SIZE 18","SIZE 12"}};
int[] state=new int [ITEM.length];
Choice[] chc =new Choice[ITEM.length];
Label lab =new Label();
void set(String name,String style,String size)
{setFont (new Font(name,
parseInt(style.substring(style.length()-1)),
parseInt(size .substring(size .length()-2))));
String f=getFont().toString(); // Component
lab.setText (f.substring(f.indexOf(',')+1,f.indexOf(']')));
}
public void itemStateChanged(ItemEvent e) // ItemListener
{loop:for(int i=0;i<ITEM.length;i++)
for(int j=0;j<ITEM[i].length;j++)
if (e.getItem().toString().equals(ITEM[i][j]))
{state[i]=j;break loop;}
set(ITEM[0][state[0]],ITEM[1][state[1]],ITEM[2][state[2]]);
}
public void start() // overrides Applet
{set(ITEM[0][state[0]],ITEM[1][state[1]],ITEM[2][state[2]]);
add (lab); // Container
for(int i=0;i<ITEM.length;i++)
{add (chc[i]=new Choice()); // Container
for(int j=0;j<ITEM[i].length;j++)
{chc[i] .add(ITEM[i][j]);
}chc[i] .addItemListener(this); // this FontChoice
} } } // FlowLayout is default for Applet
//****************************************************************
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
<!--***************** FontChoice.html *************************-->
<meta http-equiv="content-type"
content="text/html;charset=ISO-8859-15" >
<title> FontChoice </title>
<applet code="FontChoice.class" width="636" height="210" >
FontChoice
</applet>
<!--***************** width=Hochformat height=7*max(size) *****-->
Fig. 14.1.1b: FontChoice Darstellung
Der Konstruktor für die Klasse java.awt.Font (s. Dokumentation)
Font(String name,int style,int size)
verlangt als erstes Argument einen String für den Font-Namen name,
z.B. Familienname "SansSerif" oder "Serif" oder "Monospaced",
als zweites Argument einen int-Wert für den Font-Stil style, z.B.
3 (Wert von Font.BOLD+Font.ITALIC) oder 2 (Wert von Font.ITALIC)
oder 1 (Wert von Font.BOLD) oder 0 (Wert von Font.PLAIN), und als
drittes Argument einen int-Wert für die Font-Pixel-Grösse size,
z.B. 30 oder 24 oder 18 oder 12.
"Serif", diese Bezeichnung entstand am Anfang des 19. Jahrhunderts aus holländisch "schreef" (geschrieben, lat. scribere), ist
eine Verschnörkelung mit Fuß-Keilen, die von der babylonischen
Keilschrift über das Hebräische auf das späte Römische und gegen
Ende des 15. Jahrhunderts auf die deutsche (Schwabacher) Druckschrift übertragen wurde. "Monospaced" Text besteht aus Zeichen
gleicher Breite. ITALIC ist eine schräg fließende Handschrift. Der
Font-Stil size gibt die Höhe des Textes in Pixeln an.
Im folgenden Beispiel LaufSchrift enthält das HTML-Dokument
LaufSchrift.html ein applet-Element und darin ein param-Element
mit Attributen name="text" und value="Laufschrift nach links". Das
zugehörige Applet LaufSchrift.java liest den Text auf den String
text=getParameter("text"); ein und gibt den Text über die Graphics
-Methode g.drawString(text,x,y); wieder aus. Die Breite des Textes
ist abfragbar mit der Methode getFontMetrics(Font) aus der Klasse
java.awt.FontMetrix.
//********************** LaufSchrift.java ************************
// Laufschrift nach links. *
// Der text der Schrift ist als Parameter vorgebbar. *
//****************************************************************
// java.lang. O b j e c t Runnable
import static java.lang.Thread.sleep; // | |||`Thread
import static java.lang.System.err; // | ||`System
import java.awt.*; // Graphics'Component'`FontMetrics
import java.applet.Applet; // Applet'
public class LaufSchrift extends Applet implements Runnable
{String text;
int width,textwidth,shift,x,y;
public void paint(Graphics g) // overrides Component
{g.drawString(text,x,y);}
public void run() // Runnable
{for(;;)
{if (x<=-textwidth)
{x=width;} // Neuanfang rechts
else {x-=shift;} // Lauf nach links
try {sleep(100);}
catch (InterruptedException e){err.println(e.toString());}
repaint (); // calls update() with 'clear' and paint()
}
}
public void start() // overrides Applet
{ width =getWidth(); // Component
int height=getHeight(); // Component
setFont (new Font("Serif",Font.ITALIC,height*3/4)); // Comp.
text=getParameter("text"); // Applet
textwidth=getFontMetrics(getFont()) // Component
.stringWidth(text); // FontMetrics
shift=textwidth/text.length()/4;
x=width;
y=height*2/3;
new Thread(this).start(); // this LaufSchrift, calls run()
} // calls update() with 'clear' and calls paint()
}
//****************************************************************
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
<!--***************** LaufSchrift.html ************************-->
<meta http-equiv="content-type"
content="text/html;charset=ISO-8859-15" >
<title> LaufSchrift </title>
<applet code="LaufSchrift.class" width="636" height="180">
<param name="text" value="Laufschrift nach links" >
LaufSchrift
</applet>
<!--***************** width=Hochformat height=size*4/3 ********-->
Fig. 14.1.1c: LaufSchrift Darstellung
Alle 100 Millisekunden wird der Schirm gelöscht, x um shift nach
links verschoben und g.drawString(text,x,y); erneut aufgerufen.
Beim Verlassen des linken Randes, d.h. x<=-textwidth, wird der
Text wieder rechts neu angesetzt, d.h. x=width.
Bild-Graphik des Pakets java.awt (Advanced Windowing Toolkit)
wird gestaltet mit Methoden der Klasse Graphics durch Überschreiben der Methode paint(Graphics) der Klasse Component, z.B.
drawLine(int x1,int y1,int x2,int y2) (Net, unten)
fillRect(int x ,int y ,int width,int height) (update, unten)
drawOval(int x ,int y ,int width,int height) (CupApplet, 1.2.2)
drawArc (int x ,int y ,int width,int height,
int startAngle,int arcAngle) (CupApplet, 1.2.2)
Am Anfang ruft ein Applet nacheinander die Methoden init() und
start() auf, die leer sind, falls sie nicht vom Programmierer
überschrieben wurden. Es folgt der Aufruf der Methode
update(Graphics), die den Bildschirm löscht und mit der aktuellen
Hintergrundfarbe füllt, im folgenden 'clear' genannt, und die
Methode paint(Graphics) aufruft, die leer ist, falls sie nicht vom
Programmierer überschrieben wurde.
public void update(Graphics g)
{g.setColor(getBackground()); // 'clear', d.h.
g.fillRect(0,0,getWidth(),getHeight()); // Loeschen des
g.setColor(getForeGround()); // Bildschirms
paint(g);
}
Aus dem Programmlauf heraus, z.B. aus einer Listener-Methode,
kann durch Aufruf der Methode repaint() die Methode update(Graphics) und implizit die Methode paint(Graphics) aufgerufen werden.
Am Ende ruft das Applet die Methode stop() auf, die leer ist,
falls sie nicht vom Programmierer überschrieben wurde.
Im folgenden Beispiel Net werden fortlaufend Linien vom Mausdruck-Punkt zu allen vorherigen Mausdruck-Punkten gezogen.
Damit durch repaint() und implizit durch update(Graphics) nicht
die Linien zwischen vorherigen Mausdruck-Punkte gelöscht werden,
überschreiben wir update(Graphics) mit einer Version ohne 'clear':
public void update(Graphics g)
{paint(g);}
Es ist nicht möglich, an Stelle von repaint() direkt paint(g)
aufzurufen, da an der Aufruf-Stelle im Listener keine Graphics g
erklärt ist.
//*************************** Net.java ***************************
// Durch Mausdruck-Punkte aufgespanntes Netz *
//****************************************************************
// java.lang. O b j e c t Iterable
import java.util.Vector; // || |||`Vector<T>
import java.awt.event.*; // MouseEvent'| ||`MouseAdapter
import java.awt.*; // Component'Point'`Graphics
import java.applet.Applet; // Applet'
public class Net extends Applet
{Point p;
Vector<Point> v=new Vector<Point>();//implements Iterable
public void paint(Graphics g) // overrides Component
{
for(Point each:v)
{g.drawLine (p.x,p.y,each.x,each.y);}
}
public void update(Graphics g) // overrides Component
{
paint (g);
} // update() without 'clear' calls paint()
public void start() // overrides Applet
{
addMouseListener // Component
(new MouseAdapter() // listen mousePressed
{public void mousePressed(MouseEvent e) // MouseListener
{ p=new Point(e.getX(),e.getY());
v.addElement(p);
repaint (); // calls update() without 'clear'
}
}
);
} // calls update() without 'clear'
}
//****************************************************************
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
<!--***************** Net.html ********************************-->
<meta http-equiv="content-type"
content="text/html;charset=ISO-8859-15" >
<title> Net </title>
<applet code="Net.class" width="636" height="318" >
Net
</applet>
<!--***************** width=Hochformat height=width/2 *********-->
Fig. 14.1.2a: Net Darstellung
Hätte man im Beispiel Net, ähnlich wie in den Beispielen Listener
und FontChoice, die Schnittstelle MouseListener implementiert,
public class Net extends Applet implements MouseListener ,
dann hätte man nicht nur die Methode mousePressed(MouseEvent),
sondern auch die übrigen Methoden -Clicked, -Entered, -Extended,
-Released der Schnittstelle implementieren müssen. Für Schnittstellen mit vielen Methoden, empfiehlt sich die Verwendung eines
Adapters, hier MouseAdapter, für den nur die benötigte Methode,
hier mousePressed(MouseEvent), implementiert werden muss.
Im nachfolgenden Beispiel Eyes wird ein Augenpaar durch zwei
Kreise dargestellt. In den Augen bewegen sich schwarz gefüllte
kleine Kreise als Pupillen so, dass der Eindruck entsteht, als
folgten die Augen der Bewegung des Maus-Zeigers. Anders als im vorigen Beispiel Net, in dem die alte Linien-Graphik erhalten blieb
und die neue Linie eingefügt wurde, wird in diesem Beispiel die
alte Augen-Graphik gelöscht und das Augenpaar neu gezeichnet. Die
Methode repaint() ruft die nicht überschriebene Methode update
(Graphics) auf, die mit dem Löschen 'clear' des Bildschirms beginnt, bevor sie paint(Graphics) aufruft.
//**************************** Eyes.java *************************
// Augenpupillen folgen frei bewegter (moved) Maus. *
//****************************************************************
// java.lang. Object
import java.awt.event.*; // MouseEvent'||`MouseMotionAdapter
import java.awt.*; // Component'`Graphics
import java.applet.Applet; // Applet'
public class Eyes extends Applet
{int size; // Augen-Groesse
int[][] p=new int[2][2]; // Pupillen-Koordinaten
public void paint(Graphics g) // overrides Component
{g.drawOval (size ,size ,size ,size ); // Augen-Kreisbog.
g.drawOval (3*size ,size ,size ,size ); // "
g.fillOval (p[0][0],p[0][1],size/3,size/3); // Pupill-Kreisfl.
g.fillOval (p[1][0],p[1][1],size/3,size/3); // "
}
public void start() // overrides Applet
{ size=getWidth()/5; // Component
addMouseMotionListener // listenes to mouseMoved(), Component
(new MouseMotionAdapter()
{public void mouseMoved(MouseEvent e) // overrides MM-Adapter
{int[] m={e.getX(),e.getY()}; // Maus-Koordinaten
int[][] d={{m[0]-size* 4/3,m[1]-size*4/3}, // Maus-Augen
{m[0]-size*10/3,m[1]-size*4/3}}; // Abstaende
int[] r={(int)Math.sqrt(d[0][0]*d[0][0]+d[0][1]*d[0][1])
,(int)Math.sqrt(d[1][0]*d[1][0]+d[1][1]*d[1][1])
}; // Maus-Augen radiale Abstaende
for(int i=0;i<2;i++)
if (r[i]>size/3) // falls Maus ausserhalb Auge:
for(int j=0;j<2;j++)
{d[i][j]=d[i][j]*size/3/r[i];} // invert Abstaende
p=new int[][]
{{d[0][0]+size* 4/3,d[0][1]+size*4/3},
{d[1][0]+size*10/3,d[1][1]+size*4/3}};
repaint();// calls update() with 'clear' and calls paint()
}
}
);
} // calls update() with 'clear' and calls paint()
}
//****************************************************************
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
<!--***************** Eyes.html *******************************-->
<meta http-equiv="content-type"
content="text/html;charset=ISO-8859-15" >
<title> Eyes </title>
<applet code="Eyes.class" width="636" height="382" >
Eyes
</applet>
<!--***************** width=Hochformat height=width*3/5 *******-->
Fig. 14.1.2b: Eyes Darstellung
Zum Anordnen von Layout-Komponenten, wie z.B. Fertig-Teile
Label, Button, TextField oder Fertig-Menu Choice, werden im
Paket java.awt verschiedene Layouts angeboten, die alle die
Schnittstelle LayoutManager implementieren,
FlowLayout in "Schrift-Reihenfolge" (Listener, 14.1.1)
GridLayout in "Matrix-Reihenfolge" (Puzzle, 14.1.3)
BorderLayout in "Windrosen-Reihenfolge" (DialogApplet, 14.1.3)
GridBagLayout in "flexibler Reihenfolge" (siehe Dokumentation)
CardLayout zum "Karten-Durchblättern" (siehe Dokumentation)
Voreingestellt sind FlowLayout für Applet (14) und BorderLayout
für Dialog (14.1.4). Bestandteile von Zeilen in FlowLayout werden
zentriert angeordnet. Bestandteile von Zeilen in BorderLayout werden linksbündig angeordnet.
Explizites Setzen eines Layout ist möglich mit der in Container
vereinbarten Methode
setLayout(LayoutManager) .
Im folgenden Beispiel Puzzle werden Anzeigetasten Button in Gitterform (grid) angeordnet durch Setzen von GridLayout.
//************************* Puzzle.java **************************
// Folge 8..1 umordnen in Folge 1..8 im 3*3 Gitter (GridLayout). *
// Verschieben der Knoepfe (Button) durch Maus-Anklicken. *
// Die Gitterabmessungen rows, cols sind als Parameter angebbar. *
//****************************************************************
// java.lang. Object
import static java.lang.Integer.parseInt; // |||`Integer
import java.awt.event.*; // ActionEvent'|| ActionListener
import java.awt.*; // Component'`GridLayout
// Container'`Button
import java.applet.Applet; // Applet'
public class Puzzle extends Applet implements ActionListener
{
int cols,leng;
Button[] b;
public void actionPerformed(ActionEvent e) // ActionListener
{int n=parseInt(e.getActionCommand()),
dn=
/*links*/ n%cols-1>=0 &&b[n-1].getLabel().equals("0")?-1 :
/*rechts*/n%cols+1<cols &&b[n+1].getLabel().equals("0")? 1 :
/*oben*/ n-cols>=0 &&b[n-cols].getLabel().equals("0")?-cols:
/*unten*/ n+cols<leng&&b[n+cols].getLabel().equals("0")? cols:
0 ;
if (dn!=0)
{b[n+dn].setLabel(b[n].getLabel());
b[n+dn].setVisible( true); // paints button, Component
b[n] .setLabel("0");
b[n] .setVisible(false); // clears button, Component
}
}
public void start() // overrides Applet
{int rows=parseInt(getParameter("rows")); // Applet
cols=parseInt(getParameter("cols")); // Applet
leng=rows*cols;
setFont (new Font("SansSerif",Font.BOLD,getHeight()/rows));
setLayout(new GridLayout(rows,cols)); // Container
b=new Button[leng];
for(int i=0;i<leng;i++)
{ b[i]=new Button (String.valueOf(leng-i-1));
b[i].setActionCommand(String.valueOf(i));
b[i].addActionListener(this); // this Puzzle
add (b[i]); // Container
}
b[leng-1].setVisible(false); // clears button, Component
}
}
//****************************************************************
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
<!--***************** Puzzle.html *****************************-->
<meta http-equiv="content-type"
content="text/html;charset=ISO-8859-15" >
<title> Puzzle </title>
<applet code="Puzzle.class" width="636" height="318" >
<param name="rows" value="3" >
<param name="cols" value="3" >
Puzzle
</applet>
<!--***************** width=Hochformat height=width/2 *********-->
Fig. 14.1.3: Puzzle Darstellung
Der Leser wird im Puzzle ein altes Kinderspiel wiedererkennen.
Durch Maus-Anklicken der dem leeren Feld benachbarten Spielsteine
verschiebt man die Steine solange, bis sie mit ihren Nummern in
Schriftreihenfolge von 1 bis 8 angeordet sind. Die Gestalt rows*
cols des Puzzle kann über Parameter-Elemente <param...> und darin
gesetzte Attribute name="rows" value="3" und name="cols" value="3"
mit getParameter() abgefragt werden.
Im folgenden Beispiel DialogApplet wird ein Applet erzeugt, das
durch Anklicken der Anzeigetaste "Dialog" ein Dialog-Fenster erzeugt und mit setVisible(true) sichtbar macht, siehe actionPerformed(ActionEvent) aus DialogApplet:
DialogWindow dia=new DialogWindow();
dia.setVisible (true);
Im Konstruktor von DialogWindow wird ein neuer Dialog konstruiert
mit super(new Frame(),"DialogWindow",true). Durch den Wert true
für den dritten Parameter wird bestimmt, dass das Schreiben im auf-
rufenden Fenster DialogField blockiert ist, solange DialogWindow
geöffnet ist.
Das DialogWindow dient zum Schreiben eines Textes in das
DialogApplet. Dazu schreibt man den Text zunächst in das TextField
fld des DialogWindow und klickt auf die Anzeigetaste "Text into
DialogApplet".
Dadurch wird der Text aus dem TextField fld des DialogWindow dia
gelesen mit der Methode getText() und in das Label lab des DialogApplets geschrieben mit der Methode setText(String), siehe actionPerformed(ActionEvent) aus DialogApplet:
lab.setText(dia.fld.getText());
Danach wird das DialogWindow mit der Methode dispose() wieder unsichtbar gemacht, siehe actionPerformed(ActionEvent) aus DialogWindow.
Für Dialog ist BorderLayout voreingestellt (vgl. 14.1.3), d.h.
die auf dem Bildschirm erscheinende Fläche von DialogWindow ist
unterteilt nach den Himmelsrichtungen.
----------------------------
N O R T H
--------
----------
--------
WEST
CENTER
EAST
--------
----------
--------
S O U T H
----------------------------
In unserem Beispiel wird in NORTH ein Label "NORTH", in WEST ein
Label "TextField:", im CENTER ein TextField fld, in EAST ein
Button but und in SOUTH ein Label "SOUTH" eingefügt:
add(new Label ("NORTH" ),BorderLayout.NORTH );
add(new Label ("TextField:"),BorderLayout.WEST );
add (fld ,BorderLayout.CENTER);
add (but ,BorderLayout.EAST );
add(new Label ("SOUTH" ),BorderLayout.SOUTH );
Für die Abfrage der Bildschirmgröße verwenden wir die Methode
getDefaultToolkit() aus der Klasse java.awt.Toolkit.
Ort und Größe des Dialogs müssen mit setLocation(Point) und
setSize(Dimension) festgelegt werden.
//********************** DialogApplet.java ***********************
// Dialog-Fenster zur TextField-Eingabe ins Applet *
//****************************************************************
// java.lang. O b j e c t
import java.awt.event.*;//ActionEvent'|||||| ActionListener
import java.awt.*; // C o m p o n e n t'||||`FlowLayout
// TextComponent'Container'|| |||`BorderLayout
// TextField'Window'|Label'| ||`Dimension
// Frame'| |Button' |`Point
// Dialog' | `------,
import java.applet.Applet; // `Applet |
import static java.awt.Toolkit.getDefaultToolkit; // `Toolkit
class DialogWindow extends Dialog implements ActionListener
{TextField fld=new TextField(8);
public DialogWindow() // DW constr.
{super (new Frame(),"DialogWindow",true); // D constr.
Dimension scr=getDefaultToolkit().getScreenSize();
setLocation (new Point(scr.width/7,scr.height/6)); //Comp
setSize (new Dimension(scr.width/3,scr.height/6));//Comp
Button but=new Button("Text into DialogApplet");
but.addActionListener(this); // this DialogWindow
add(new Label ("NORTH" ),BorderLayout.NORTH );// Container
add(new Label ("TextField:"),BorderLayout.WEST );// Container
add (fld ,BorderLayout.CENTER);// Container
add (but ,BorderLayout.EAST );// Container
add(new Label ("SOUTH" ),BorderLayout.SOUTH );// Container
}
public void actionPerformed(ActionEvent e) // ActionListener
{dispose ();
}
} // BorderLayout is default for Dialog
public class DialogApplet extends Applet implements ActionListener
{Label lab=new Label(" old Text ");
public void actionPerformed(ActionEvent e) // ActionListener
{DialogWindow dia=new DialogWindow();
dia.setVisible(true); // Component
lab.setText (dia.fld.getText()); // TextComponent
}
public void start() // overrides Applet
{setFont (new Font("SansSerif",Font.BOLD,getHeight()/4));
add (lab); // Container
Button but=new Button("Dialog");
add (but); // Container
but.addActionListener(this); // this DialogApplet
}
} // FlowLayout is default for Applet
//****************************************************************
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
<!--***************** DialogApplet.html ***********************-->
<meta http-equiv="content-type"
content="text/html;charset=ISO-8859-15" >
<title> DialogApplet </title>
<applet code="DialogApplet.class" width="636"height="212">
DialogApplet
</applet>
<!--***************** width=Hochformat height=width/3 *********-->
Fig. 14.1.4: DialogApplet Darstellung
Jedes Applet, z.B. auch unser DialogApplet, erlaubt "FensterSchließen" durch Anklicken des Window-Leisten-Knopfs "X" ohne explizites Einprogrammieren von dispose().
Ein Dialog, z.B. unser DialogWindow, ist aber kein Applet und
würde für das "Fenster-Schließen" durch Anklicken des DialogWindow - Leisten - Knopfs "X" explizites Einprogrammieren von
dispose() erfordern, vgl. CupApplication (3.4). In unserem Fall
ist dies nicht erforderlich, da das DialogWindow durch Anklicken
von "Text into DialogAplet" schließt, siehe actionPerformed(ActionEvent) aus DialogWindow.
Auf dem Bildschirm hat jedes Pixel Farbanteile in Rot-Grün-Blau
(RGB), auf dem Drucker Farbanteile in Yellow-Magenta-Cyan (YMC).
Das folgende Beispiel ColorCube erlaubt jede gewünschte Farbkombination als Rot-Grün-Blau-Farbkugel sichtbar zu machen.
//*********************** ColorCube.java *************************
// Farbwuerfel aus R(ot)G(ruen)B(lau)-Kugeln. *
// Die Anzahl lums>1 der Farbstufen ist als Parameter vorgebbar. *
//****************************************************************
// java.lang. O b j e c t
import static java.lang.Integer.parseInt; // | ||`Integer
import java.awt.*; // Graphics'Component'`Color
import java.applet.Applet; // Applet'
public class ColorCube extends Applet
{int size,lums,lins;
int siz(double d)
{return(int) (d*(size-1)/(lins-1));} // Groessen-Skalierung
int col(double d)
{return(int) (d*255 /(lums-1));} // Farb-Skalierung
public void paint(Graphics g) // overrides Component
{ size=getWidth(); // Component
lums=parseInt(getParameter("lums")); // Applet
lins=lums*(lums+1);// Kreismittelpunkte u.Raender
for(int i=0;i<256;i++)
{g.setColor(new Color(i,i,i));
g.fillPolygon(new int[]{0,(2*size-1)*(255-i)/255,0},
new int[]{0,0,(2*size-1)*(255-i)/255},3);
} // grauer Hintergrund diagonal: weiss bis schwarz
for(int lin=0;lin<lins;lin++)
{g.drawLine(0,siz(lin),siz(lins-1),siz(lin));
g.drawLine(siz(lin),0,siz(lin),siz(lins-1));
} // weisse Linien fuer Kreismittelpunkte u.Raender
for(int red=0;red<lums;red++)
for(int gre=0;gre<lums;gre++)
for(int blu=0;blu<lums;blu++)
{int r=siz(0.1*red+ 0.3 *lums),
x=siz(0.9*red+(0.2+blu)*lums),
y=siz(0.9*red+(0.2+gre)*lums);
g.setColor(new Color(col(red),col(gre),col(blu)));
g.fillOval(x,y,2*r,2*r);
g.setColor(new Color(0,0,0));
g.drawOval(x,y,2*r,2*r);
} // farbige Kreise mit schwarzem Rand
}
} // implicite start() of Applet calls paint()
//****************************************************************
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
<!--***************** ColorCube.html **************************-->
<meta http-equiv="content-type"
content="text/html;charset=ISO-8859-15" >
<title> ColorCube </title>
<applet code="ColorCube.class" width="636" height="636" >
<param name="lums" value="5" >
ColorCube
</applet>
<!--***************** width=Hochformat height=width=size ******-->
Fig. 14.1.5: ColorCube Darstellung
Zum Setzen der Farbe aus Rot-Grün-Blau Anteilen benutzt man die
in java.awt.Graphics vereinbarte Methode setColor(Color) und den
Konstruktor Color(int,int,int) der Klasse java.awt.Color. Z.B.
wird im obigen Applet ColorCube das Schwarz für den Rand der
Kreise wie folgt gewählt:
g.setColor(new Color(0,0,0));
Die drei Farbanteile haben jeweils 256 verschiedene Intensitäten von 0..255. Im allgemeinen wird aber ein Bildschirm oder ein
Drucker nicht jede Grundfarbe in 256 verschiedenen Nuancen signifikant verschieden darstellen können.
Im obigen Beispiel Color-Cube wurden vergröbernd nur 5 verschiedene Intensitäten von 0..4 gewählt, um die Anzahl 5*5*5=125 der
Farbkugeln so klein zu halten, dass die Farben der Kugeln noch gut
zu unterscheiden sind. Durch Wahl eines anderen Werts für das
Attribut value im param-Element des applet-Elements können die
Intensitäten verändert werden.
zu Frage
abdeckbare Antwort
---------------------------------------------
--------------------
14.1 Welche 3 Attribute müssen in einem
code, width, height
applet-Element immer gesetzt sein?
14.1 Von welchem Typ sind alle Werte von
vom Typ String
Attributen, z.B. width=?, z.B. value=?
14.1.1/2 In welchem Paket sind ...Event-
java.awt.event
und ...Adapter - Klassen vereinbart?
14.1.1 In welcher Klasse sind add...Liste-
java.awt.Component
ner-Methoden vereinbart?
14.1.2 Welche Methoden werden von start()
update() u. paint()
und repaint() implizit aufgerufen?
14.1.2 Wie kann man den clear-Effekt von
update() mit Body
update() vermeiden?
{paint(g);}
überschreiben, vgl.
Beispiel Net
14.1.2 Schreibe ein Applet, welches die
siehe mousePressed
X,Y-Koordinaten bei Mausdruck ausgibt!
mit getX(), getY()
14.1.3 In welchem Paket sind ...Layout-
java.awt
Klassen vereinbart?
14.1.3 Welches Layout ist voreingestellt:
- für Applet ?
FlowLayout
- für Dialog ?
BorderLayout
14.1.4 Die Klassen Frame, Dialog und Applet
eröffnen alle ein Fenster. Welche der
Klassen erlaubt
- automatisches Schließen des Fensters
Applet, vgl. z.B.
mit Klick auf das Fensterleisten-X?
CupApplet 1.2.2
- programmiertes Schließen des Fensters
Frame, vgl. z.B.
mit addWindowListener(WindowAdapter)
CupApplication 3.4
und erst dann mit Klick auf das
Dialog, vgl. z.B.,
Fensterleisten-X?
DialogApplet 14.1.4
betr. new Color():
14.1.5 Zu ColorCube:
red->(yel+mag)/2.0
Ändere das red/gre(en)/blu(e)-Modell um
gre->(yel+cya)/2.0
in ein yel(low)/mag(enta)/cya(n)-Modell
blu->(mag+cya)/2.0