import java.awt.*
importiert
(AWT=Abstract Windowing Toolkit). Um diese geschickt anzuwenden, muss
man möglichst viele der
Bezeichner dieser bereitgestellten Klassen, Interfaces, Methoden und Daten mitsamt ihrer
Bedeutung genau kennen. Um deren Funktionen zu erproben, bleibt einem
häufig nichts anderes übrig, als zu experimentieren. Ich
werde im folgenden alle die Bezeichner
von Klassen, Methoden und
Attributen blau kennzeichnen, die ich den
Java-Paketen entnommen habe.
Die hier verwendete Java-Basisklasse heißt Frame. Sie ermöglicht mit ihrem Konstruktor und ihren Methoden die Erzeugung und Ausgestaltung eines Grafikfensters.
Ich werde im folgenden erklären, wie man ein Grafikfenster, in
dem eine Kurve gezeichnet werden soll, konstruiert und ausgestaltet. Das
einfachste Beispiel wird eine Unterklasse von Frame namens Grafik0 sein. Hier werden
Sie lernen, wie man ein Grafikfenster einer bestimmten Höhe und
Breite erstellt (setSize()), dessen
Hintergrundfarbe festlegt (setBackground()) und eine Kurve in
einer bestimmten Farbe zeichnet (paint()), indem winzige Geradenstücke
aneinandergereiht werden (drawLine()).
In einem zweiten Beispiel (Grafik1) wird
die Kurve von einem Parameter dt
abhängen, den man interaktiv
mit Hilfe einer Schaltfläche, die Teil des Grafikfensters ist,
ändern und anschließend eine neue Zeichnung durch einen
Mausklick veranlassen kann. Die Java-Hilfsmittel sind hier schon
komplexer, insbesondere muss ein Interface namens ActionListener implementiert werden, das mit
seinen Methoden gestattet, auf Mausklicks zu reagieren.
Das Herz aller Grafikklassen ist die Methode paint(), die die Struktur
besitzt und deren Block stets ausgeführt wird, wenn ein Objekt einer Unterklasse von Frame in einempublic void paint(Graphics g){..........}
main()
-Block einer Applikationsklasse initialisiert
wird.
Dabei werden i.a. Methoden der Klasse Graphics bzw. dessen Objekte
wie die selbsterklärenden Methoden setColor() oder drawLine() benutzt
werden. Das konkret "gezeichnete" Grafikobjekt wird oben mit
g
bezeichnet und ist ein Objekt der Klasse Graphics. Der Farbigkeit dienen "Farbkonstenten" der Klasse Color, wie z.B. Color.blue.
Unsere Klasse Grafik0 (s.u.) wird durch
aus der Klasse Frame abgeleitet, d.h. ist eine Unterklasse von Frame. So würde mittelspublic class Grafik0 extends Frame
innerhalb derFrame w = new Frame("Leeres Grafikfenster"); w.setsize(400,300); w.visible(true);
main()
-Methode einer Applikationsklasse ein leeres
Fenster der Größe 400x300 Pixel mit einer Titelleiste, die
den Text Leeres Grafikfenster enthält, erzeugt. Die Klasse
Frame hat also einen Konstruktor, der
einen String
übergibt, der den Titel der Titelleiste
definiert. setSize() und visible() sind offensichtlich Methoden der
Klasse Frame bzw. seiner Objekte (wie
hier w
).
In unserer Klasse Grafik0
wird der
Applikationsblock
die Erzeugung eines Fensters mit Zeichnung auslösen. Die Titelleiste zeigt die Formel der parametrisierten Kurve (was sich dahinter verbirgt, wird in der Vorlesung kurz erklärt).static public void main( String [] args ){ Grafik0 obj=new Grafik0( //Konstruktor uebergibt String: "x=2.1*cos(2pi*t)+0.1*sin(2pi*10*t);"+ "y=2.1*sin(2pi*t)-0.1*cos(2pi*10*t);"+ "0<=t<=1, Schrittweite dt. B.W. 19.9.00"); }//Ende main()
Unsere Klasse Grafik0 sieht wie folgt aus:
Die entscheidende Zeile ist die Zeile in der Methodeimport java.awt.*; import java.awt.event.*; import java.util.*; public class Grafik0 extends Frame{ //DATEN: double dt=0.001; //Zeichenschrittweite int H=700, B=800; //Fensterhoehe, -Breite //Ende DATEN //KONSTRUKTOR: public Grafik0 (String title ) { super( title ); // Fenstertitel uebergeben // Schliessbarkeit des Fensters ermoeglichen: addWindowListener( new WindowAdapter() { public void windowClosing( WindowEvent w ) { setVisible(false); dispose(); System.exit(0); }//Ende windowClosing() }//Ende des Konstruktors WindowAdapter() );//Ende addWindowListener() //Hintergrundfarbe des Fensters setzen: setBackground(Color.lightGray); //Groesse des Fensters setzen: setSize(B,H); //Fenster in die linke obere Ecke positionieren: setLocation( 0, 0 ); //Fenster sichtbar machen: setVisible( true ); }//Ende KONSTRUKTOR Grafik0 //METHODEN: public double[] sincos(double t){ double[] x=new double[2]; //Nur hier steckt Mathematik: x[0]=2.1*Math.cos(2*Math.PI*t)+0.1*Math.sin(2*Math.PI*20*t); x[1]=2.1*Math.sin(2*Math.PI*t)-0.1*Math.cos(2*Math.PI*20*t); return x; }//Ende sincos() public short[] skalierung(double x, double y){ double xMax=3, xMin=-xMax, yMax=3, yMin=-yMax; short[] i = new short[2]; i[0]=(short) (B/10 +B*0.9*(x-xMin)/(xMax-xMin)); i[1]=(short) (H/10 +H*0.9*(y-yMin)/(yMax-yMin)); return i; }//Ende skalierung() //paint() legt fest, was gezeichnet wird: public void paint (Graphics g) { //Farbe der auszugebenden Grafik setzen g.setColor(Color.red); double t=0.0; double[] x=sincos(t); short[] i1=new short[2]; short[] i0=skalierung(x[0],x[1]); // Linien zeichnen while (t<=1) { t+=dt; x=sincos(t); i1=skalierung(x[0],x[1]); g.drawLine(i0[0],i0[1],i1[0],i1[1]); i0[0]=i1[0];i0[1]=i1[1]; }//Ende while }//Ende paint() static public void main( String [] args ){ Grafik0 obj=new Grafik0( "x=2.1*cos(2pi*t)+0.1*sin(2pi*20*t);"+ "y=2.1*sin(2pi*t)-0.1*cos(2pi*20*t);"+ "0<=t<=1, B.W. 11.8.01"); }//Ende main() } // Ende class Grafik0
main()
, in der ein Objekt namens obj
der Klasse
Grafik0 deklariert und initialisiert wird. Da Grafik0
eine Unterklasse von Frame ist, wird
ein Grafikfenster der im Konstruktor vorgesehenen Größe
(setSize()) und Hintergrundfarbe
(setBackground()) und Position
(setLocation()) geöffnet und der
paint()-Block abgearbeitet, der eine
durch t
parametrisierte Kurve mit Hilfe der Methode
drawLine() zeichnet. Etwas kryptisch
ist der paint()-Parameter
g
als Objekt der Klasse Graphics, welche alle grafischen Methoden wie
drawLine(), setColor() definiert.
Die 4 Parameter von drawLine() sind
jeweils 2 Pixel-Paare, die die
Koordinaten im Grafikfenster bestimmen, wobei der Ursprung die obere
linke Ecke ist und die Pixel-Ordinate nach unten, die Pixel-Abszisse
nach rechts zeigt. Die Methode skalierung() dient der Umrechnung
von den mathematischen Koordinaten in die Pixel-Koordinaten. Die
Grafikfenstergröße wird ebenfalls in Pixel gemessen, wobei
die Auflösung des Bildschirms eingeht.
Ich empfehle, einfach einige Experimente mit diesem Programm durchzuführen, indem kleine Änderungen vorgenommen werden.
Unsere Klasse Grafik1 (s.u.) wird durch
aus der Klasse Frame abgeleitet und implementiert ein Interface (das ähnlich wie eine Oberklasse Daten und Methoden vererbt) namens ActionListener. Dieses Interface ermöglicht es, mit seinen Methoden (u.a. actionPerformed()) auf Events ("Aktionen") wie einen Mausklick oder das Verändern eines Textfeldes im Grafikfenster zu reagieren.public class Grafik1 extends Frame implements ActionListener{ //...................... }
Grafikfenster werden i.a. mit verschiedenen Arten von Schaltflächen versehen. Die Festlegung deren Gestalt ist eine Layoutaufgabe. Auch hier gibt es mächtige Java-Klassen und -Methoden, von denen ich nur Panel, Button, TextField, Label, setLayout(), GridLayout(), setForeground(), setBackground() erwähne. Diese werden im folgenden genauso wenig näher erläutert wie die Methode addWindowListener(), die das Schließen des Fensters ermöglicht. Bei eigenen Versuchen orientiere man sich einfach an den folgenden Beispielen.
Unsere Klasse Grafik1 sieht wie folgt aus:
Ich werde in der Vorlesung zu dieser Klasse weitere Erklärungen geben. Diese werden verständlicher, wenn man das Programm ausführt.import java.awt.*; import java.awt.event.*; import java.util.*; public class Grafik1 extends Frame implements ActionListener{ //DATEN: double dt=0.3; //Zeichenschrittweite /*Der Inhalt des folgenden Textfeldes kann interaktiv veraendert werden - s. Methode actionPerformed()*/ TextField tf1 =new TextField(""+dt);//Ein Textfeld wird konstruiert //Ende DATEN //KONSTRUKTOR: public Grafik1 (String title ) { super( title ); //Konstruktor von Frame //Schliessbarkeit des Fensters ermoeglichen: addWindowListener( new WindowAdapter() { public void windowClosing( WindowEvent w ) { setVisible(false); dispose(); System.exit(0); }//Ende windowClosing() }//Ende des Konstruktors WindowAdapter() );//Ende addWindowListener() /*ein Panel besteht aus Labels, Textfeldern, Buttons. np1 wird am unteren Rand ("South") angebracht, enthält die Beschriftung "Neu zeichnen" uns soll auf einen Mausklick reagieren. np2 besteht aus einem Label mit Beschriftung "dt" und einem Textfield, das den Zahlenwert von dt enthält und das interaktiv verändert werden kann. */ Panel np1 = new Panel(); Panel np2 = new Panel(); //Ein Button wird konstruiert Button rc=new Button("Neu zeichnen"); Label l1=new Label("dt=",Label.CENTER); np1.setLayout(new GridLayout(1,1));//Eine Zeile, 1 Spalte) np1.setForeground(Color.red); np1.add(rc); add("South",np1); np2.setLayout(new GridLayout(1,1)); np2.setBackground(Color.yellow); add("North",np2); np2.add(l1); np2.add(tf1); rc.addActionListener(this); /*addActionListener steht in der Klasse Button zur Verfuegung. Ihr Argument ist vom Typ ActionListener - einem Interface, das von unserer Klasse Grafik1 implementiert wird und die Methode actionPerformed() zur Verfuegung stellt, die unten ueberlagert wird. Durch diese Mathode reagiert das Programm auf das Druecken des Buttons "Neu Zeichnen" */ //Hintergrundfarbe des Fensters setzen: setBackground(Color.lightGray); //Groesse des Fensters setzen: setSize(800,700); // Fenster in die linke obere Ecke positionieren: setLocation( 0, 0 ); // Fenster sichtbar machen: setVisible( true ); }//Ende KONSTRUKTOR Grafik1 //METHODEN: public double[] sincos(double t){ double[] x=new double[2]; //Nur hier steckt Mathematik: x[0]=2.1*Math.cos(2*Math.PI*t)+ 0.4*Math.sin(2*Math.PI*5.03*t); x[1]=1.9*Math.sin(2*Math.PI*t) -0.6*Math.cos(2*Math.PI*5.03*t); return x; }//Ende sincos() public short[] skalierung(double x, double y){ double xMax=3, xMin=-xMax, yMax=3, yMin=-yMax; short[] i = new short[2]; i[0]=(short) (120 +600*(x-xMin)/(xMax-xMin)); i[1]=(short) ( 50 +600*(y-yMin)/(yMax-yMin)); return i; }//Ende skalierung() //paint() legt fest, was gezeichnet wird: public void paint (Graphics g) { //paint() ist eine Methode der Oberklasse Frame: super.paint( g ); // Farbe der auszugebenden Grafik setzen: g.setColor(Color.red); double t=0.0; double[] x=sincos(t); short[] i1=new short[2]; short[] i0=skalierung(x[0],x[1]); // Linien zeichnen: while (t<=100) { t+=dt; x=sincos(t); i1=skalierung(x[0],x[1]); g.drawLine(i0[0],i0[1],i1[0],i1[1]); i0[0]=i1[0];i0[1]=i1[1]; }//Ende while }//Ende paint() public void actionPerformed(ActionEvent e){ String cmd; cmd=e.getActionCommand(); if (cmd.equals("Neu zeichnen")){ dt=(new Double(tf1.getText())).doubleValue(); repaint(); //Methode von Frame }//Ende if }//Ende actionPerformed() static public void main( String [] args ){ Grafik1 obj=new Grafik1( "x=2.1*cos(2pi*t)+0.4*sin(2pi*5.03*t);"+ "y=1.9*sin(2pi*t)-0.6*cos(2pi*5.03*t);"+ "0<=t<=100, Schrittweite dt. B.W. 19.9.00"); }//Ende main() } // Ende class Grafik1
Die Methode actionPerformed()
reagiert auf einen Mausklick auf den mit "Neu Zeichnen" beschrifteten
Button, indem mittels Aufruf von repaint() der Zeichenvorgang wiederholt wird,
allerdings mit dem aktuellen, interaktiv veränderbaren Wert des
Parameters dt
, der mittels Methode getText() "abgelesen" und mittels der Methode
doubleValue() der Klasse Double, dessen Konstruktor den String des
Textfeldes tf
übergibt, in eine double
-Zahl verwandelt wird.