From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001
From: Sven Eisenhauer
Date: Fri, 10 Nov 2023 15:11:48 +0100
Subject: add new repo
---
.../hjp5/html/k100221.html | 520 +++++++++++++++++++++
1 file changed, 520 insertions(+)
create mode 100644 Master/Reference Architectures and Patterns/hjp5/html/k100221.html
(limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100221.html')
diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100221.html b/Master/Reference Architectures and Patterns/hjp5/html/k100221.html
new file mode 100644
index 0000000..39e95e3
--- /dev/null
+++ b/Master/Reference Architectures and Patterns/hjp5/html/k100221.html
@@ -0,0 +1,520 @@
+
+
+
+Handbuch der Java-Programmierung, 5. Auflage
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+33.2.1 Anforderungen
+
+
+In diesem Abschnitt wollen wir uns ein konkretes Beispiel zur Komponentenentwicklung
+ansehen. Dazu soll eine einstellige 7-Segment-Anzeige entwickelt werden,
+die in der Lage ist, die Ziffern 0 bis 9 darzustellen. Des weiteren
+sollen folgende Eigenschaften realisiert werden:
+
+- Die Anzeige soll in der Größe skalierbar sein und sich
+zu allen Layoutmanagern kompatibel verhalten.
+
- Die 7-Segment-Anzeige soll auf Mausklicks reagieren. Nach einem
+Mausklick soll sie den Fokus erhalten. Nach Drücken der linken
+Maustaste soll der Anzeigewert herunter- und nach Drücken der
+rechten Maustaste heraufgezählt werden. Wird während des
+Mausklicks die [UMSCHALT]-Taste
+gedrückt, so soll lediglich der Fokus zugewiesen werden, der
+Wert aber unverändert bleiben.
+
- Der Anzeigewert soll durch Drücken der Tasten [+]
+und [-] herauf- bzw. heruntergezählt
+werden. Wird eine Zifferntaste gedrückt, so soll die Anzeige
+auf diesen Wert gesetzt werden.
+
- Eine Anzeige, die den Fokus hat, soll visuell von einer ohne Fokus
+unterscheidbar sein. Der Fokus soll weiterhin - wie unter Windows
+üblich - mit Hilfe der Tasten [TAB]
+und [UMSCHALT]+[TAB]
+von einem Dialogelement zum nächsten weitergereicht werden können.
+
+
+
+
+
+33.2.2 Bildschirmanzeige
+
+
+Die Architektur unserer Anzeigekomponente ist denkbar einfach. Wir
+definieren dazu eine neue Klasse Segment7,
+die aus Canvas
+abgeleitet wird. Segment7
+besitzt eine Membervariable digit,
+die den aktuellen Anzeigewert speichert. Dieser kann mit den öffentlichen
+Methoden getValue und setValue
+abgefragt bzw. gesetzt werden. Die Klasse bekommt zwei Konstruktoren,
+die es erlauben, den Anzeigewert wahlweise bei der Instanzierung zu
+setzen oder die Voreinstellung 0 zu verwenden.
+
+
+Segment7
+überlagert die Methoden getPreferredSize
+und getMinimumSize
+der Klasse Component,
+um den Layoutmanagern die gewünschte Größe mitzuteilen:
+
+
+
+
+
+
+public Dimension getPreferredSize()
+
+public Dimension getMinimumSize()
+
+
+ |
+
+java.awt.Component |
+
+
+
+
+Beide Methoden liefern ein Objekt der Klasse Dimension,
+also ein rechteckiges Element mit einer Höhe und Breite. getPreferredSize
+teilt dem Layoutmanager mit, welches die gewünschte Größe
+der Komponente ist, und getMinimumSize
+gibt an, welches die kleinste akzeptable Größe ist. Der
+Layoutmanager FlowLayout
+beispielsweise verwendet getPreferredSize,
+um die Größe der Komponente zu bestimmen. GridLayout
+gibt die Größe selbst vor und passt sie an die Gitterelemente
+an. Durch Aufruf von pack
+kann allerdings auch GridLayout
+dazu veranlaßt werden, die gewünschte Größe
+der Komponenten abzufragen und zur Dimensionierung des Fensters (und
+damit letztlich zur Dimensionierung der Einzelkomponenten) zu verwenden.
+Seit dem JDK 1.1 gibt es noch eine dritte Methode getMaximumSize,
+mit der die Komponente ihre maximale Größe mitteilen kann.
+Sie wird in unserem Beispiel nicht benötigt.
+
+
+Zur Darstellung der Leuchtdiodenanzeige auf dem Bildschirm wird die
+Methode paint
+überlagert; in ihr befindet sich die Logik zur Darstellung der
+sieben Segmente (siehe Abbildung 33.1).
+In Segment7
+wurden dazu drei Arrays digits,
+polysx und polysy
+definiert, die die Belegung der Segmente für jede einzelne Ziffer
+darstellen und die Eckpunkte jedes einzelnen Segments vorgeben.
+
+
+paint
+verwendet das Array digits,
+um herauszufinden, welche Segmente zur Darstellung der aktuellen Ziffer
+verwendet werden. Für jedes der beteiligten Segmente wird dann
+aus den Arrays polysx und polysy
+das passende Polygon gebildet und mit fillPolygon
+angezeigt. Als interne Berechnungseinheit werden zwei Parameter dx
+und dy verwendet, die beim Aufruf
+von paint
+aus dem für die Komponente verfügbaren Platz berechnet werden.
+
+
+
+
+
+
+Abbildung 33.1: Der Aufbau der 7-Segment-Anzeige
+
+
+
+
+33.2.3 Ereignisbehandlung
+
+
+Wie in Kapitel 28
+erwähnt, erfolgt die Ereignisbehandlung in selbstdefinierten
+Komponenten üblicherweise auf der Basis des vierten vorgestellten
+Architekturmodells. Bei diesem werden die Ereignisse nicht durch registrierte
+Listener-Klassen bearbeitet, sondern durch Überlagern der Methoden
+process...Event der Klasse Component.
+
+
+Damit die Ereignisse tatsächlich an diese Methoden weitergegeben
+werden, müssen sie zuvor durch Aufruf von enableEvents
+und Übergabe der zugehörigen Ereignismaske aktiviert werden.
+Da wir Component-, Focus-, Key- und Mouse-Ereignisse behandeln wollen,
+rufen wir enableEvents
+mit den Konstanten AWTEvent.COMPONENT_EVENT_MASK,
+AWTEvent.FOCUS_EVENT_MASK,
+AWTEvent.MOUSE_EVENT_MASK
+und AWTEvent.KEY_EVENT_MASK
+auf. Beim Überlagern dieser Methoden sollte in jedem Fall der
+entsprechende Ereignishandler der Superklasse aufgerufen werden, um
+die korrekte Standard-Ereignisbehandlung sicherzustellen.
+
+
+Die Reaktion auf Mausklicks wird durch Überlagern der Methode
+processMouseEvent
+realisiert. Hier wird zunächst überprüft, ob es sich
+um ein MOUSE_PRESSED-Ereignis
+handelt, also ob eine der Maustasten gedrückt wurde. Ist
+dies der Fall, wird dem Anzeigeelement durch Aufruf von requestFocus
+der Eingabefokus zugewiesen.
+
+
+Anschließend wird überprüft, ob die [UMSCHALT]-Taste
+gedrückt wurde. Ist das der Fall, wird die Ereignisbehandlung
+beendet, andernfalls wird der Anzeigewert hoch- bzw. heruntergezählt,
+je nachdem, ob die rechte oder linke Maustaste gedrückt wurde.
+Am Ende von processMouseEvent
+wird in jedem Fall super.processMouseEvent
+aufgerufen, um sicherzustellen, dass die normale Ereignisbehandlung
+aufgerufen wird.
+
+
+Ein selbstdefiniertes Dialogelement bekommt nicht automatisch den
+Fokus zugewiesen, wenn mit der Maus darauf geklickt wird. Statt dessen
+muss es selbst auf Mausklicks reagieren und sich - wie zuvor beschrieben
+- durch Aufruf von requestFocus
+selbst den Fokus zuweisen. Bei jeder Fokusänderung wird ein Focus-Event
+ausgelöst, das wir durch Überlagern der Methode processFocusEvent
+bearbeiten. Hier unterscheiden wir zunächst, ob es sich um ein
+FOCUS_GAINED-
+oder FOCUS_LOST-Ereignis
+handelt, und setzen eine interne Statusvariable hasfocus
+entsprechend. Diese wird nach dem anschließenden Aufruf von
+repaint
+verwendet, um in paint
+durch Modifikation der Anzeigefarbe ein visuelles Feedback zu geben.
+Hat ein Element den Fokus, so ist die Farbe der Anzeigesegmente gelb,
+andernfalls rot.
+
+
+Seit dem JDK 1.1 gibt es einen Mechanismus, der es erlaubt, mit den
+Tasten [TAB] und [UMSCHALT]+[TAB]
+zwischen den Eingabefeldern eines Dialogs zu wechseln. Genauer gesagt
+wird dadurch der Fokus an das nächste Element weiter- bzw. zum
+vorigen zurückgegeben. Da diese Vorgehensweise nicht bei jedem
+Dialogelement sinnvoll ist, kann das Dialogelement sie durch Überlagern
+der Methode isFocusTraversable
+selbst bestimmen. Liefert isFocusTraversable
+den Rückgabewert true,
+so nimmt das Objekt an der [TAB]-Behandlung
+teil, andernfalls nicht. Die Klasse Segment7
+überlagert isFocusTraversable
+und gibt true
+zurück. So kann mit [TAB]
+und [UMSCHALT]+[TAB]
+wie besprochen zwischen den 7-Segment-Anzeigen gewechselt werden.
+
+
+
+
+Ein Dialogelement enthält nur dann Tastatureingaben, wenn es
+den Fokus hat. Durch den zuvor beschriebenen Mechanismus des Aufrufs
+von requestFocus
+stellen wir sicher, dass nach einem Mausklick bzw. nach dem Wechsel
+des Fokus mit [TAB] und [UMSCHALT]+[TAB]
+Tastaturereignisse an das Element gesendet werden. Diese werden durch
+Überlagern der Methode processKeyEvent
+behandelt. Wir überprüfen darin zunächst, ob das Ereignis
+vom Typ KEY_PRESSED
+ist, und besorgen dann mit getKeyChar
+den Wert der gedrückten Taste. Ist er '+', so wird der Anzeigewert
+um 1 erhöht, bei '-' entsprechend verringert. Wurde eine der
+Zifferntasten gedrückt, so erhält das Anzeigeelement diesen
+Wert. Anschließend wird durch Aufruf von repaint
+die Anzeige neu gezeichnet.
+
+
+Ein Component-Ereignis brauchen wir in unserem Beispiel nur, damit
+wir dem Dialogelement unmittelbar nach der Anzeige auf dem Bildschirm
+den Fokus zuweisen können. Dazu überlagern wir die Methode
+processComponentEvent
+und überprüfen, ob das Ereignis vom Typ COMPONENT_SHOWN
+ist. In diesem Fall wird requestFocus
+aufgerufen, andernfalls passiert nichts.
+
+
+Damit ist die Konstruktion der Komponente auch schon abgeschlossen.
+Durch die Definition von getPreferredSize
+und getMinimumSize
+und die automatische Skalierung in der paint-Methode
+verhält sich unsere neue Komponente so, wie es die Layoutmanager
+von ihr erwarten. Daher kann sie wie eine vordefinierte Komponente
+verwendet werden. Hier ist der Quellcode von Segment7:
+
+
+
+
+
+
+
+
+001 /* Segment7.java */
+002
+003 import java.awt.*;
+004 import java.awt.event.*;
+005
+006 class Segment7
+007 extends Canvas
+008 {
+009 private int digit;
+010 private boolean hasfocus;
+011 private int[][] polysx = {
+012 { 1, 2, 8, 9, 8, 2}, //Segment 0
+013 { 9,10,10, 9, 8, 8}, //Segment 1
+014 { 9,10,10, 9, 8, 8}, //Segment 2
+015 { 1, 2, 8, 9, 8, 2}, //Segment 3
+016 { 1, 2, 2, 1, 0, 0}, //Segment 4
+017 { 1, 2, 2, 1, 0, 0}, //Segment 5
+018 { 1, 2, 8, 9, 8, 2}, //Segment 6
+019 };
+020 private int[][] polysy = {
+021 { 1, 0, 0, 1, 2, 2}, //Segment 0
+022 { 1, 2, 8, 9, 8, 2}, //Segment 1
+023 { 9,10,16,17,16,10}, //Segment 2
+024 {17,16,16,17,18,18}, //Segment 3
+025 { 9,10,16,17,16,10}, //Segment 4
+026 { 1, 2, 8, 9, 8, 2}, //Segment 5
+027 { 9, 8, 8, 9,10,10}, //Segment 6
+028 };
+029 private int[][] digits = {
+030 {1,1,1,1,1,1,0}, //Ziffer 0
+031 {0,1,1,0,0,0,0}, //Ziffer 1
+032 {1,1,0,1,1,0,1}, //Ziffer 2
+033 {1,1,1,1,0,0,1}, //Ziffer 3
+034 {0,1,1,0,0,1,1}, //Ziffer 4
+035 {1,0,1,1,0,1,1}, //Ziffer 5
+036 {1,0,1,1,1,1,1}, //Ziffer 6
+037 {1,1,1,0,0,0,0}, //Ziffer 7
+038 {1,1,1,1,1,1,1}, //Ziffer 8
+039 {1,1,1,1,0,1,1} //Ziffer 9
+040 };
+041
+042 public Segment7()
+043 {
+044 this(0);
+045 }
+046
+047 public Segment7(int digit)
+048 {
+049 super();
+050 this.digit = digit;
+051 this.hasfocus = false;
+052 enableEvents(AWTEvent.COMPONENT_EVENT_MASK);
+053 enableEvents(AWTEvent.FOCUS_EVENT_MASK);
+054 enableEvents(AWTEvent.MOUSE_EVENT_MASK);
+055 enableEvents(AWTEvent.KEY_EVENT_MASK);
+056 }
+057
+058 public Dimension getPreferredSize()
+059 {
+060 return new Dimension(5*10,5*18);
+061 }
+062
+063 public Dimension getMinimumSize()
+064 {
+065 return new Dimension(1*10,1*18);
+066 }
+067
+068 public boolean isFocusTraversable()
+069 {
+070 return true;
+071 }
+072
+073 public void paint(Graphics g)
+074 {
+075 Color darkred = new Color(127,0,0);
+076 Color lightred = new Color(255,0,0);
+077 Color yellow = new Color(255,255,0);
+078 //dx und dy berechnen
+079 int dx = getSize().width / 10;
+080 int dy = getSize().height / 18;
+081 //Hintergrund
+082 g.setColor(darkred);
+083 g.fillRect(0,0,getSize().width,getSize().height);
+084 //Segmente
+085 if (hasfocus) {
+086 g.setColor(yellow);
+087 } else {
+088 g.setColor(lightred);
+089 }
+090 for (int i=0; i < 7; ++i) { //alle Segmente
+091 if (digits[digit][i] == 1) {
+092 Polygon poly = new Polygon();
+093 for (int j = 0; j < 6; ++j) { //alle Eckpunkte
+094 poly.addPoint(dx*polysx[i][j],dy*polysy[i][j]);
+095 }
+096 g.fillPolygon(poly);
+097 }
+098 }
+099 //Trennlinien
+100 g.setColor(darkred);
+101 g.drawLine(0,0,dx*10,dy*10);
+102 g.drawLine(0,8*dy,10*dx,18*dy);
+103 g.drawLine(0,10*dy,10*dx,0);
+104 g.drawLine(0,18*dy,10*dx,8*dy);
+105 }
+106
+107 public int getValue()
+108 {
+109 return digit;
+110 }
+111
+112 public void setValue(int value)
+113 {
+114 digit = value % 10;
+115 }
+116
+117 protected void processComponentEvent(ComponentEvent event)
+118 {
+119 if (event.getID() == ComponentEvent.COMPONENT_SHOWN) {
+120 requestFocus();
+121 }
+122 super.processComponentEvent(event);
+123 }
+124
+125 protected void processFocusEvent(FocusEvent event)
+126 {
+127 if (event.getID() == FocusEvent.FOCUS_GAINED) {
+128 hasfocus = true;
+129 repaint();
+130 } else if (event.getID() == FocusEvent.FOCUS_LOST) {
+131 hasfocus = false;
+132 repaint();
+133 }
+134 super.processFocusEvent(event);
+135 }
+136
+137 protected void processMouseEvent(MouseEvent event)
+138 {
+139 if (event.getID() == MouseEvent.MOUSE_PRESSED) {
+140 requestFocus();
+141 if (!event.isShiftDown()) {
+142 if (event.isMetaDown()) {
+143 setValue(getValue() + 1); //increment by 1
+144 } else {
+145 setValue(getValue() + 9); //decrement by 1
+146 }
+147 }
+148 repaint();
+149 }
+150 super.processMouseEvent(event);
+151 }
+152
+153 protected void processKeyEvent(KeyEvent event)
+154 {
+155 if (event.getID() == KeyEvent.KEY_PRESSED) {
+156 char key = event.getKeyChar();
+157 if (key >= '0' && key <= '9') {
+158 setValue(key - '0');
+159 repaint();
+160 } else if (key == '+') {
+161 setValue(getValue() + 1); //increment by 1
+162 repaint();
+163 } else if (key == '-') {
+164 setValue(getValue() + 9); //decrement by 1
+165 repaint();
+166 }
+167 }
+168 super.processKeyEvent(event);
+169 }
+170 }
+
+ |
+
+Segment7.java |
+
+
+
+Listing 33.1: Eine 7-Segment-Anzeige
+
+
+
+
+
--
cgit v1.2.3