32
Benutzeroberfl ächen mit Java 4.1.2011 1 Michael Weiss

Benutzeroberflächen mit Java 4.1.20111Michael Weiss

Embed Size (px)

Citation preview

Page 1: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

1Michael Weiss

Benutzeroberflächen mit Java

4.1.2011

Page 2: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

2

import javax.swing.*;/** * @author Michael Weiss * @version 4.1.2011 */public class Uhr{ private JFrame hatJFrame;

public Uhr() { hatJFrame = new JFrame("Fenster"); hatJFrame.setVisible(true); // <- vorher sieht man gar nichts! }

public static void main(String args[]) { try { // 5 Zeilen, damit sich das Programm ins OS integriert UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { System.err.println("no system look and feel available"); }; new Uhr(); }}

Ausgangspunkt JFrame

4.1.2011Michael Weiss

Page 3: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

3

Ausgangspunkt JFrame

4.1.2011Michael Weiss

Das Resultat überzeugt noch nicht vollständig:

import javax.swing.*;import java.awt.*;public Uhr() { hatJFrame = new JFrame("Fenster"); hatJFrame.setMinimumSize(new_Dimension(400,300)); hatJFrame.setVisible(true); } }

Ergebnis:

Verbesserung:

Page 4: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

4

Fenster aufteilen

4.1.2011Michael Weiss

Das Fenster soll am Schluss etwa so aussehen:

Wenn man das Fenster skaliert, soll der Bereich oben rechts nicht breiter werden.

Page 5: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

5

JPanel

4.1.2011Michael Weiss

Die einzelnen Fensterteile sind Objekte vom Typ JPanel. Wir fügen nun gemäss dem gewünschten Layout 3 JPanels in das JFrame ein.

public Uhr() { hatJFrame = new JFrame("Fenster"); hatJFrame.setMinimumSize(new Dimension(400,300)); hatJFrame.setLayout(new BorderLayout()); hatZeichenJPanel_=_new_JPanel(); hatJFrame.add(hatZeichenJPanel,_BorderLayout.CENTER); hatSliderJPanel_=_new_JPanel(); hatJFrame.add(hatSliderJPanel,_BorderLayout.SOUTH); hatButtonJPanel_=_new_JPanel(); hatJFrame.add(hatButtonJPanel,_BorderLayout.EAST);  hatJFrame.setVisible(true); }

Der sichtbare Effekt ist gleich null, daher fügen wir 2 Buttons ein.

Page 6: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

6

GridLayout und JButton

4.1.2011Michael Weiss

hatButtonJPanel.setLayout(new GridLayout(2,1)); // Zeilen, Spalten hatPauseJButton = new JButton("Pause"); hatButtonJPanel.add(hatPauseJButton); hatStellenJButton = new JButton("stellen"); hatButtonJPanel.add(hatStellenJButton);

Wir fügen 2 Buttons in das hatButtonJPanel ein. Dazu soll der Platz in diesem Panel in gleich grosse Rechteckzellen eingeteilt werden, was durch Zuweisung eines GridLayouts geschieht.

Wieder überzeugt das Resultat nur teilweise:

Der "Pause"-Knopf blinkt blau, wie wenn er aktiv wäre (man sagt: wie wenn er den Focus hätte).

Die beiden Knöpfe füllen den gesamten "EAST"-Raum aus.

Page 7: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

7

Keine Buttons mit Focus...

4.1.2011Michael Weiss

hatButtonJPanel.setLayout(new GridLayout(2,1)); // Zeilen, Spalten hatPauseJButton = new JButton("Pause"); hatPauseJButton.setFocusable(false); hatButtonJPanel.add(hatPauseJButton); hatStellenJButton = new JButton("stellen"); hatStellenJButton.setFocusable(false); hatButtonJPanel.add(hatStellenJButton);

...und bitte nicht so riesig!Eigentlich sollen die Buttons nur den oberen Teil des EAST-Gebiets füllen:

Dazu unterteilen wir das EAST-Gebiet erneut mit einem BorderLayout und stecken das ButtonJPanel in das NORTH-Gebiet dieser Unterteilung.

Page 8: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

8

Geschachtelte Layouts

4.1.2011Michael Weiss

hatEastJPanel_=_new_JPanel(); hatJFrame.add(hatEastJPanel,_BorderLayout.EAST); hatEastJPanel.setLayout(new_BorderLayout()); hatButtonJPanel = new JPanel(); hatEastJPanel.add(hatButtonJPanel,_BorderLayout.NORTH); hatButtonJPanel.setLayout(new GridLayout(2,1)); // Zeilen, Spalten hatPauseJButton = new JButton("Pause"); hatPauseJButton.setFocusable(false); hatButtonJPanel.add(hatPauseJButton); hatStellenJButton = new JButton("stellen"); hatStellenJButton.setFocusable(false); hatButtonJPanel.add(hatStellenJButton);

schon besser.... aber ein wenig freien Rand rund um die Buttons würde man sich schon noch wünschen!

Page 9: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

9

Ränder einrichten

4.1.2011Michael Weiss

hatEastJPanel = new JPanel(); hatJFrame.add(hatEastJPanel, BorderLayout.EAST); hatEastJPanel.setLayout(new BorderLayout()); hatButtonJPanel = new JPanel(); // unsichtbaren 10 Pixel breiten Rand um das hatButtonJPanel hatButtonJPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); hatEastJPanel.add(hatButtonJPanel, BorderLayout.NORTH); // Das GridLayout_auch_noch_mit_Abständen_zwischen_den_Zellen_versehen hatButtonJPanel.setLayout(new GridLayout(2,1,10,10)); // Zeilen, Spalten, horiz. & vert. Abstand hatPauseJButton = new JButton("Pause"); hatPauseJButton.setFocusable(false); hatButtonJPanel.add(hatPauseJButton); hatStellenJButton = new JButton("stellen"); hatStellenJButton.setFocusable(false); hatButtonJPanel.add(hatStellenJButton);

nicht schlecht!

Page 10: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

10

Slider

4.1.2011Michael Weiss

hatJSlider = new JSlider(JSlider.HORIZONTAL, -10, 10, 1); hatJSlider.setMajorTickSpacing(1); hatJSlider.setPaintTicks(true); hatJSlider.setPaintLabels(true); hatSliderJPanel.add(hatJSlider);

Leider hat Java seine eigenen Vorstellungen davon, was eine optimale Slider-Breite ist.

Nun noch ein Schiebebalken zur Einstellung der Geschwindigkeit der Uhr.

Page 11: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

11

Slider, verschönert

4.1.2011Michael Weiss

hatJSlider = new JSlider(JSlider.HORIZONTAL, -10, 10, 1); hatJSlider.setMajorTickSpacing(1); hatJSlider.setPaintTicks(true); hatJSlider.setPaintLabels(true); hatJSlider.setMinimumSize(new_Dimension(hatJFrame.getWidth()-20,50)); hatJSlider.setPreferredSize(new_Dimension(hatJFrame.getWidth()-20,50)); hatSliderJPanel.add(hatJSlider);

Einige Versuche führen schliesslich auf die folgende Lösung:

Das kommt dem erwünschten Aussehen schon recht nahe. Nur die Uhr fehlt noch!

Page 12: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

12

import javax.swing.*;import java.awt.*;/** * Ein JPanel um drin zu zeichnen. * * @author Michael Weiss * @version 4.1.2011 */public class ZeichenJPanel extends JPanel{ // überschreibe die entsprechende Methode der Überklasse protected void paintComponent(Graphics pGraphics) { // Damit die Buttons, Slider, Labels etc. weiterhin gezeichnet werden, // rufen wir als erstes paintComponent() der Überklasse auf. super.paintComponent(pGraphics); // Ab hier zeichnen wir selbst. }}

In ein JPanel hineinzeichnen

4.1.2011Michael Weiss

• Im Gegensatz zur SuM-Bibliothek stellen uns die Java-Standardbibliotheken kein Fenster zur Verfügung, in das wir einfach jederzeit zeichnen können.

• Dafür weiss Java, wann ein JPanel neu gezeichnet werden muss und ruft dann die Methode paintComponent(Graphics pGraphics) auf.

• Standardmässig zeichnet diese Methode aber nur die in ihr enthaltenen GUI-Komponenten (Buttons, Slider, Labels etc.) neu. Formen wie Kreise, Linien usw. müssen wir selbst zeichnen.

• Zu diesem Zweck entwickeln wir eine Unterklasse von JPanel, welche paintComponent(Graphics pGraphics)überschreibt:

Page 13: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

13

hatUhrJPanel = new JPanel(); hatJFrame.add(hatUhrJPanel, BorderLayout.CENTER); hatUhrZeichenJPanel_=_new_ZeichenJPanel(); hatJFrame.add(hatUhrZeichenJPanel,_BorderLayout.CENTER); 

In ein JPanel hineinzeichnen

4.1.2011Michael Weiss

Das erfordert auch kleine Änderungen an der Klasse Uhr:

Bis jetzt haben wir aber noch gar nichts gezeichnet!

Page 14: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

14

// ab hier zeichnen wir selbst. pGraphics.setColor(Color.BLACK); int xmin = 0, width = 0, ymin = 0, height = 0; if(this.getWidth() > this.getHeight()) { height = this.getHeight() - 10; ymin = 5; xmin = (this.getWidth() - height) / 2; width = height; } else { width = this.getWidth() - 10; xmin = 5; ymin = (this.getHeight() - width) / 2; height = width; } pGraphics.drawOval(xmin, ymin, width, height);

Wie zeichnet man eine Uhr?

4.1.2011Michael Weiss

• Die Uhr sollte ein möglichst grosses Quadrat ausfüllen. Wir bestimmen die Koordinaten dieses Quadrats und beginnen dann mit einem Kreis.

• Das Graphics-Objekt wird uns von Java mitgegeben, damit wir seine Methoden zum zeichnen benutzen können.

• Manchmal braucht man mehr Methoden, als sie das Graphics-Objekt zur Verfügung stellt. pGraphics zeigt aber in Wirklichkeit gar nicht auf ein reines Graphics-Objekt, sondern auf ein Graphics2D-Objekt, welches weitere Zeichnungsmehtoden zur Verfügung stellt.

• Um pGraphics als Zeiger auf ein Graphics2D-Objekt zu verwenden, müssen wir casten:

Graphics2D kenntGraphics = (Graphics2D)pGraphics; // danach mit kenntGraphics arbeiten.

Page 15: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

15

Die Uhrzeiger

4.1.2011Michael Weiss

• Es macht Sinn, eine Klassenhierarchie einzuführen:

• Die Standard-Bibliothek von Java erlaubt es, Formen als Kombinationen von Linienzügen, Ellipsen, Kreisbogenstücken und anderen Grundformen auszudrücken und diese Formen später als Ganzes zu transformieren.

• Wir beschreiben daher die Zeiger in einer bequemen Lage (12-Uhr-Stellung) und in einem handlichen Koordinatensystem (Ursprung im Mittelpunkt der Uhr, Radius der Uhr gleich 50 Einheiten).

• Die anschliessende Transformationsarbeit (Drehen der Zeiger entsprechend der gewünschten Zeit, Einpassen der Zeiger in ein Fenster, dessen Grösse sich verändern kann) ist für alle Uhrzeiger gleich und wird daher in der abstrakten Überklasse erledigt.

Page 16: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

16

import java.awt.*;import java.awt.geom.*;/** * @author Michael Weiss * @version 5.1.2011 */public class Minutenzeiger extends Uhrzeiger{ public Minutenzeiger() { super(Color.BLACK); super.hatForm.moveTo(0,-15); super.hatForm.lineTo(2,0); super.hatForm.lineTo(0,45); super.hatForm.lineTo(-2,0); super.hatForm.closePath(); }}

Der Minutenzeiger

4.1.2011Michael Weiss

x

y

hatForm ist vom Typ Path2D.float und kann mehrere Grafikobjekte aufnehmen. Es wird in der Überklasse erzeugt.

Der Stundenzeiger sieht praktisch gleich aus.

Page 17: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

17

import java.awt.*;import java.awt.geom.*;/** * @author Michael Weiss * @version 5.1.2011 */public class Sekundenzeiger extends Uhrzeiger{ public Sekundenzeiger() { super(Color.RED); super.hatForm.moveTo(-0.5,-16); super.hatForm.lineTo(0.5,-16); super.hatForm.lineTo(0.5,48); super.hatForm.lineTo(-0.5,48); super.hatForm.closePath(); super.hatForm.append(new Ellipse2D.Float(-3,-3,6,6), false); }}

Der Sekundenzeiger

4.1.2011Michael Weiss

x

y

Page 18: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

18

Affine Transformation

4.1.2011Michael Weiss

x

y

affine Transformation

x

y

Page 19: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

19

Erster Schritt: Drehung

4.1.2011Michael Weiss

x

y

Drehung

x

y

• Da die Drehung im Uhrzeigersinn erfolgt, ist der Drehwinkel negativ.• Java stellt die benötigte Koordinatenumrechnung (ein Spezialfall einer affinen

Transformation) direkt zur Verfügung.

Page 20: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

20

Drehung in Java

4.1.2011Michael Weiss

import java.awt.*;import java.awt.geom.*;/** * @author Michael Weiss * @version 5.1.2011 */public abstract class Uhrzeiger{ protected Path2D.Float hatForm; private Color zColor; // Jeder Uhrzeiger wird durch einen Pfad repräsentiert, der in ein Quadrat von 100 Einheiten Seitenlänge // passt, und dessen Koordinatenursprung sich in der Quadratmitte befindet. public Uhrzeiger(Color pColor) { zColor = pColor; hatForm = new Path2D.Float(); }  public void zeichne(Graphics2D pGraphics2D, int pH, int pV, int pBreite, int pHoehe, double pWinkel) { AffineTransform_lRotation_=_AffineTransform.getRotateInstance(-pWinkel_/_180.0_*_Math.PI); AffineTransform_lAffineTransform_=_new_AffineTransform(0.01*pBreite,0,0,-0.01*pHoehe,pH+0.5*pBreite,pV+_0.5*pHoehe); lAffineTransform.concatenate(lRotation); Path2D.Float lForm_=_ (Path2D.Float)(hatForm.clone()); lForm.transform(lAffineTransform); pGraphics2D.setColor(zColor); pGraphics2D.fill(lForm); } }

Der Drehwinkel muss im Bogenmass angegeben werden, daher / 180 * .

Page 21: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

21

Zweiter Schritt: Transformation auf JPanelkoordinaten

4.1.2011Michael Weiss

Transfor-mation

x'

y'

x

y

A(0|0)B(50|0)

C(0|50)

A'(x0+w/2|y0+h/2)

B'(x0+w|y0+h/2)

C'(x0+w/2|y0)

x0 x0+w

y0

y0+h

Page 22: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

22

Berechnung der Transformation

4.1.2011Michael Weiss

Wenn man berechnen will, welche Koordinaten (x'|y') ein Punkt im neuen Koordinatensystem haben wird, wenn er im alten Koordinatensystem die Koordinaten (x|y) hat, kann man von folgenden Gleichungen ausgehen:

x' = ax + cy + ey' = bx + dy + f

Anhand dreier vorgegebener Punkte A(xA, yA), B(xB, yB) und C(xC, yC) sowie ihrer Bildpunkte A'(xA', yA'), B'(xB', yB') und C'(xC', yC') lassen sich die Parameter a, b, c, d, e und f berechnen.

In unserem Fall sind die Punkte A(0|0), B(50|0) und C(0|50) sowie deren Bildpunkte A'(x0+w/2|y0+h/2), B'(x0+w|y0+h/2) und C'(x0+w/2|y0) gegeben. Setzen wir A und A' ein, erhalten wir

x0+w/2 = ey0+h/2 = f

Setzen wir B und B' ein und verwenden die bereits ausgerechneten Werte für e und f, erhalten wir nach kurzer Rechnung a = w/100 und b = 0. Mit C und C' finden wir schliesslich c = 0 und d = -h / 100.

Page 23: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

23

Die Transformation in Java

4.1.2011Michael Weiss

import java.awt.*;import java.awt.geom.*;/** * @author Michael Weiss * @version 5.1.2011 */public abstract class Uhrzeiger{ protected Path2D.Float hatForm; private Color zColor; // Jeder Uhrzeiger wird durch einen Pfad repräsentiert, der in ein Quadrat von 100 Einheiten Seitenlänge // passt, und dessen Koordinatenursprung sich in der Quadratmitte befindet. public Uhrzeiger(Color pColor) { zColor = pColor; hatForm = new Path2D.Float(); }  public void zeichne(Graphics2D pGraphics2D, int pH, int pV, int pBreite, int pHoehe, double pWinkel) { AffineTransform lRotation = AffineTransform.getRotateInstance(-pWinkel / 180.0 * Math.PI); AffineTransform_lAffineTransform_=_new_AffineTransform(0.01*pBreite,0,0,-0.01*pHoehe,pH+0.5*pBreite,pV+_0.5*pHoehe); lAffineTransform.concatenate(lRotation); Path2D.Float lForm_=_ (Path2D.Float)(hatForm.clone()); lForm.transform(lAffineTransform); pGraphics2D.setColor(zColor); pGraphics2D.fill(lForm); } }

w h x0 y0

Die Parameter a bis f werden in dieser Reihenfolge dem Konstruktor eines Objekts der Klasse AffineTransform übergeben.

Page 24: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

24

Hintereinanderausführung von Drehung und

Koordinatentransformation

4.1.2011Michael Weiss

import java.awt.*;import java.awt.geom.*;/** * @author Michael Weiss * @version 5.1.2011 */public abstract class Uhrzeiger{ protected Path2D.Float hatForm; private Color zColor; // Jeder Uhrzeiger wird durch einen Pfad repräsentiert, der in ein Quadrat von 100 Einheiten Seitenlänge // passt, und dessen Koordinatenursprung sich in der Quadratmitte befindet. public Uhrzeiger(Color pColor) { zColor = pColor; hatForm = new Path2D.Float(); }  public void zeichne(Graphics2D pGraphics2D, int pH, int pV, int pBreite, int pHoehe, double pWinkel) { AffineTransform lRotation = AffineTransform.getRotateInstance(-pWinkel / 180.0 * Math.PI); AffineTransform lAffineTransform = new AffineTransform(0.01*pBreite,0,0,-0.01*pHoehe,pH+0.5*pBreite,pV+ 0.5*pHoehe); lAffineTransform.concatenate(lRotation); Path2D.Float lForm_=_ (Path2D.Float)(hatForm.clone()); lForm.transform(lAffineTransform); pGraphics2D.setColor(zColor); pGraphics2D.fill(lForm); } }

Page 25: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

25

Ausführung der gesamten Transformation

4.1.2011Michael Weiss

lAffineTransform.concatenate(lRotation); Path2D.Float lForm = (Path2D.Float)(hatForm.clone()); lForm.transform(lAffineTransform); pGraphics2D.setColor(zColor); pGraphics2D.fill(lForm);

• Klonen des Zeigers (erzeugt eine echte Kopie)• Transformieren der Kopie• Farbe setzen• transformierte Kopie zeichnen (fill: ausmalen)

Page 26: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

26

Zifferblatt

4.1.2011Michael Weiss

import java.awt.*;import java.awt.geom.*;/** * Klasse Ziffernblatt: Zeichnet 12 grosse und 48 kleine Uhrstriche. * Gezeichnet wird ein Ziffernblatt, das in ein Quadrat der Seitenlänge * 100 und dem Koordinatenursprung in der Mitte passt. * * @author Michael Weiss * @version 5.1.2011 */public class Ziffernblatt{ private Path2D.Float hatForm, hatStundenstrich, hatMinutenstrich; public Ziffernblatt() { hatStundenstrich = new Path2D.Float(); hatStundenstrich.moveTo(-0.5,40); hatStundenstrich.lineTo(0.5,40); hatStundenstrich.lineTo(0.5,48); hatStundenstrich.lineTo(-0.5,48); hatStundenstrich.closePath(); hatMinutenstrich = new Path2D.Float(); hatMinutenstrich.moveTo(-0.25,45); hatMinutenstrich.lineTo(0.25,45); hatMinutenstrich.lineTo(0.25,48); hatMinutenstrich.lineTo(-0.25,48); hatMinutenstrich.closePath(); hatForm = new Path2D.Float();

Mit der selben Technik lässt sich auch ein Zifferblatt zeichnen. Dazu wird das ursprüngliche Bild eines senkrechten Ziffernstrichs 11- resp. 48-mal gedreht und jeweils in ein- und dasselbe Path2D.float-Objekt aufgenommen.

Page 27: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

27

Zifferblatt (Forts.)

4.1.2011Michael Weiss

int h = 0; while(h < 12) { Path2D.Float lStundenstrich = (Path2D.Float)(hatStundenstrich.clone()); AffineTransform lRotation = AffineTransform.getRotateInstance(-h * 30.0 / 180.0 * Math.PI); lStundenstrich.transform(lRotation); hatForm.append(lStundenstrich, false); h++; } int m = 1; while(m < 60) { if(m % 5 != 0) { Path2D.Float lMinutenstrich = (Path2D.Float)(hatMinutenstrich.clone()); AffineTransform lRotation = AffineTransform.getRotateInstance(-m * 6.0 / 180.0* Math.PI); lMinutenstrich.transform(lRotation); hatForm.append(lMinutenstrich, false); } m++; } }  public void zeichne(Graphics2D pGraphics2D, int pH, int pV, int pBreite, int pHoehe) { AffineTransform lAffineTransform = new AffineTransform(0.01 * pBreite, 0, 0, -0.01 * pHoehe, pH + 0.5*pBreite, pV + 0.5*pHoehe); Path2D.Float lForm = (Path2D.Float)(hatForm.clone()); lForm.transform(lAffineTransform); pGraphics2D.setColor(Color.BLACK); pGraphics2D.fill(lForm); }}

Page 28: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

28

Dargestellte Zeit einstellen

4.1.2011Michael Weiss

/** * Speichere die Zeit in Stunden, Minuten * und Sekunden und * berechne die Winkel der drei Uhrzeiger. * * @author Michael Weiss * @version 6.1.2011*/public class Zeit{ private int zStd, zMin; private double zSek;  public Zeit(int pStd, int pMin, double pSek) { zStd = pStd; zMin = pMin; zSek = pSek; }  

Wir benutzen eine Klasse, welche sich eine Zeit merken kann und diese in die Winkeleinstellungen der drei Uhrzeiger umrechnen kann.

public double winkelStundenzeiger() { return zStd * 30 + zMin * 0.5 + zSek * 0.5 / 60.0; } public double winkelMinutenzeiger() { return zMin * 6 + zSek * 0.1; } public double winkelSekundenzeiger() { return zSek * 6; }}

Page 29: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

29

Dargestellte Zeit einstellen

4.1.2011Michael Weiss

/** * Speichere die Zeit in Stunden, Minuten * und Sekunden und * berechne die Winkel der drei Uhrzeiger. * * @author Michael Weiss * @version 6.1.2011*/public class Zeit{ private int zStd, zMin; private double zSek;  public Zeit(int pStd, int pMin, double pSek) { zStd = pStd; zMin = pMin; zSek = pSek; }  

Wir benutzen eine Klasse, welche sich eine Zeit merken kann und diese in die Winkeleinstellungen der drei Uhrzeiger umrechnen kann.

public double winkelStundenzeiger() { return zStd * 30 + zMin * 0.5 + zSek * 0.5 / 60.0; } public double winkelMinutenzeiger() { return zMin * 6 + zSek * 0.1; } public double winkelSekundenzeiger() { return zSek * 6; }}

Erzeugt wird sie innerhalb der Klasse Uhr:

hatZeit = new Zeit(13,50,22);

Page 30: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

30

Dargestellte Zeit einstellen (2)

4.1.2011Michael Weiss

Damit das ZeichenJPanel die Uhrzeit nutzen kann, erzeugen wir eine Getter-Methode:

public Zeit zeit() { return hatZeit; }

Zudem übergeben wir dem ZeichenJPanel im Konstruktor einen Verweis auf die Klasse Uhr, so dass das ZeichenJPanel später die Methode zeit() der Klasse Uhr aufrufen kann:

hatUhrZeichenJPanel = new ZeichenJPanel(this);

Entsprechend bekommt die Klasse ZeichenJPanel einen geänderten Konstruktor:public class ZeichenJPanel extends JPanel{ private Uhrzeiger hatSekundenzeiger, hatMinutenzeiger, hatStundenzeiger; private Ziffernblatt hatZiffernblatt; private Uhr kenntUhr; public ZeichenJPanel(Uhr pUhr) { hatZiffernblatt = new Ziffernblatt(); hatSekundenzeiger = new Sekundenzeiger(); hatMinutenzeiger = new Minutenzeiger(); hatStundenzeiger = new Stundenzeiger(); kenntUhr = pUhr; }

Page 31: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

31

protected void paintComponent(Graphics pGraphics) { // damit die Buttons, Slider, Labels etc. weiterhin gezeichnet werden, // rufen wir als erstes paintComponent() der Überklasse auf. super.paintComponent(pGraphics); Graphics2D kenntGraphics2D = (Graphics2D)pGraphics; // ab hier zeichnen wir selbst. int xmin = 0, width = 0, ymin = 0, height = 0; if(this.getWidth() > this.getHeight()) { height = this.getHeight() - 10; ymin = 5; xmin = (this.getWidth() - height) / 2; width = height; } else { width = this.getWidth() - 10; xmin = 5; ymin = (this.getHeight() - width) / 2; height = width; } kenntGraphics2D.setColor(Color.BLACK); kenntGraphics2D.setStroke(new BasicStroke(width / 100)); kenntGraphics2D.drawOval(xmin, ymin, width, height); hatZiffernblatt.zeichne(kenntGraphics2D, xmin, ymin, width, height); Zeit lZeit = kenntUhr.zeit(); hatStundenzeiger.zeichne(kenntGraphics2D, xmin, ymin, width, height, lZeit.winkelStundenzeiger()); hatMinutenzeiger.zeichne(kenntGraphics2D, xmin, ymin, width, height, lZeit.winkelMinutenzeiger()); hatSekundenzeiger.zeichne(kenntGraphics2D, xmin, ymin, width, height, lZeit.winkelSekundenzeiger()); }

Dargestellte Zeit einstellen (3)

4.1.2011Michael Weiss

Und auch paintComponent() ändert sich noch ein wenig:

Page 32: Benutzeroberflächen mit Java 4.1.20111Michael Weiss

32

Fertig?

4.1.2011Michael Weiss

• Die Benutzeroberfläche ist nun fertig. • Das Programm reagiert jedoch noch auf keine Benutzereingaben!• Diese so genannte Ereignisverarbeitung behandeln wir später.