1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
|
<html>
<head>
<title>
Handbuch der Java-Programmierung, 5. Auflage
</title>
</head>
<body>
<a name="startofbody"></a>
<script language="JavaScript" src="hjp4lib.js">
</script>
<script language="JavaScript">
installKbdHandler("97,#startofbody;101,#endofbody;116,cover.html;122,k100003.html;115,search.html;105,index.html;100,JDKDOCS;112,APIDOCS;104,k100279.html;106,k100280.html;107,k100282.html;108,k100287.html");
</script>
<table border=0 cellpadding=0 cellspacing=1 width="100%">
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html"> Titel </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </a>
<td align="right">Handbuch der Java-Programmierung, 5. Auflage
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100279.html"> << </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100280.html"> < </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100282.html"> > </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100287.html"> >> </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </a>
<td align="right">Kapitel 44 - Beans
</table>
<hr>
<!-- Section -->
<a name="sectlevel2id044002"></a>
<h2>44.2 Entwurf einer einfachen Bean </h2>
<hr>
<ul>
<li><a href="k100281.html#sectlevel2id044002">44.2 Entwurf einer einfachen Bean</a>
<ul>
<li><a href="k100281.html#sectlevel3id044002001">44.2.1 Grundsätzliche Architektur</a>
<li><a href="k100281.html#sectlevel3id044002002">44.2.2 Grafische Darstellung</a>
<li><a href="k100281.html#sectlevel3id044002003">44.2.3 Eigenschaften</a>
<ul>
<li><a href="k100281.html#sectlevel4id044002003001">Objekte als Eigenschaften</a>
<li><a href="k100281.html#sectlevel4id044002003002">Indizierte Eigenschaften</a>
</ul>
<li><a href="k100281.html#sectlevel3id044002004">44.2.4 Implementierung</a>
<li><a href="k100281.html#sectlevel3id044002005">44.2.5 Verwendung der Bean</a>
</ul>
</ul>
<hr>
<p>
Wir wollen uns in diesem Abschnitt mit dem Entwurf einer einfachen
Bean beschäftigen. Dazu werden wir eine Klasse <font color="#000077"><tt>LightBulb</tt></font>
entwerfen, die eine kleine Glühlampe grafisch darstellt. Sie
kann wahlweise an- oder ausgeschaltet werden. Diese Klasse wird alle
notwendigen Eigenschaften einer Bean aufweisen und kann im GUI-Designer
und im laufenden Programm verwendet werden.
<!-- Section -->
<a name="sectlevel3id044002001"></a>
<h3>44.2.1 Grundsätzliche Architektur </h3>
<p>
Da wir eine GUI-Komponente realisieren wollen, folgen wir analog der
in <a href="k100219.html#kapitelcanvasundpanel">Kapitel 33</a> beschriebenen
Vorgehensweise und leiten unsere Klasse <font color="#000077"><tt>LightBulb</tt></font>
aus der Klasse <a href="index_c.html#ixb101712"><font color=#000080><tt>Canvas</tt></font></a>
des Pakets <a href="index_j.html#ixb100190"><font color=#000080><tt>java.awt</tt></font></a>
ab. Um die Eigenschaft der Serialisierbarkeit zu erfüllen, implementiert
die Klasse das Interface <a href="index_s.html#ixb100454"><font color=#000080><tt>Serializable</tt></font></a>.
Der Anschaltzustand wird in der Instanzvariablen <font color="#000077"><tt>lighton</tt></font>
festgehalten:
<a name="listingid044001"></a>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
<tr>
<td valign=top>
<font color="#000055">
<pre>
<font color="#555555">001 </font><font color="#0000AA">import</font> java.awt.*;
<font color="#555555">002 </font><font color="#0000AA">import</font> java.awt.event.*;
<font color="#555555">003 </font><font color="#0000AA">import</font> java.io.*;
<font color="#555555">004 </font><font color="#0000AA">import</font> java.beans.*;
<font color="#555555">005 </font>
<font color="#555555">006 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> LightBulb
<font color="#555555">007 </font><font color="#0000AA">extends</font> Canvas
<font color="#555555">008 </font><font color="#0000AA">implements</font> Serializable
<font color="#555555">009 </font>{
<font color="#555555">010 </font> <font color="#0000AA">protected</font> <font color="#006699">boolean</font> lighton;
<font color="#555555">011 </font> <font color="#0000AA">transient</font> <font color="#0000AA">protected</font> Image offimage;
<font color="#555555">012 </font> <font color="#0000AA">transient</font> <font color="#0000AA">protected</font> Image onimage;
<font color="#555555">013 </font> ...
<font color="#555555">014 </font>}</pre>
</font>
</td>
</tr>
</table>
<i>
Listing 44.1: Deklaration der Klasse LightBulb</i></p>
<!-- Section -->
<a name="sectlevel3id044002002"></a>
<h3>44.2.2 Grafische Darstellung </h3>
<p>
Die grafische Darstellung der Glühbirne soll durch das Anzeigen
von Bitmaps erfolgen, die bei der Instanzierung aus zwei <font color="#660099">gif</font>-Dateien
<font color="#660099">bulb1.gif</font> und <font color="#660099">bulb2.gif</font>
geladen werden. Abhängig vom Zustand der Variable <font color="#000077"><tt>lighton</tt></font>
wird in der überlagerten <a href="index_p.html#ixb101148"><font color=#000080><tt>paint</tt></font></a>-Methode
jeweils eine der beiden Bitmaps angezeigt. Das Verfahren entspricht
im wesentlichen dem in <a href="k100225.html#entwicklungbitmapkomponente">Abschnitt 34.1.2</a>
beschriebenen. Auch die Methoden <a href="index_g.html#ixb101706"><font color=#000080><tt>getPreferredSize</tt></font></a>
und <a href="index_g.html#ixb101715"><font color=#000080><tt>getMinimumSize</tt></font></a>
werden überlagert, damit die Komponente einem eventuell vorhandenen
Layoutmanager die gewünschte Größe (in diesem Fall
40 mal 40 Pixel) mitteilen kann.
<p>
Etwas anders als bisher beschrieben arbeitet die Routine zum Laden
der Bilddateien. Damit die Bilddatei auch gefunden wird, wenn die
Klasse aus einer <font color="#660099">.jar</font>-Datei geladen wurde
(das ist beispielsweise beim Laden von serialisierten Beans oder beim
Import in einen GUI-Designer der Fall), kann nicht einfach der Dateiname
an <a href="index_c.html#ixb100644"><font color=#000080><tt>createImage</tt></font></a>
bzw. <a href="index_g.html#ixb101732"><font color=#000080><tt>getImage</tt></font></a>
übergeben werden. Statt dessen konstruieren wir mit Hilfe des
Klassenobjekts unserer Bean und dessen Methode <a name="ixa103267"><a href="index_g.html#ixb102412"><font color=#000080><tt>getResource</tt></font></a></a>
ein <a href="index_u.html#ixb102196"><font color=#000080><tt>URL</tt></font></a>-Objekt,
das wir an <font color="#000077"><tt>createImage</tt></font> übergeben
können:
<a name="listingid044002"></a>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
<tr>
<td valign=top>
<font color="#000055">
<pre>
<font color="#555555">001 </font><font color="#0000AA">private</font> Image getImageResource(String name)
<font color="#555555">002 </font>{
<font color="#555555">003 </font> Image img = <font color="#006699">null</font>;
<font color="#555555">004 </font> <font color="#0000AA">try</font> {
<font color="#555555">005 </font> java.net.URL url = getClass().getResource(name);
<font color="#555555">006 </font> img = getToolkit().createImage(url);
<font color="#555555">007 </font> MediaTracker mt = <font color="#0000AA">new</font> MediaTracker(<font color="#006699">this</font>);
<font color="#555555">008 </font> mt.addImage(img, 0);
<font color="#555555">009 </font> <font color="#0000AA">try</font> {
<font color="#555555">010 </font> <font color="#00AA00">//Warten, bis das Image vollständig geladen ist,</font>
<font color="#555555">011 </font> mt.waitForAll();
<font color="#555555">012 </font> } <font color="#0000AA">catch</font> (InterruptedException e) {
<font color="#555555">013 </font> <font color="#00AA00">//nothing</font>
<font color="#555555">014 </font> }
<font color="#555555">015 </font> } <font color="#0000AA">catch</font> (Exception e) {
<font color="#555555">016 </font> System.err.println(e.toString());
<font color="#555555">017 </font> }
<font color="#555555">018 </font> <font color="#0000AA">return</font> img;
<font color="#555555">019 </font>}</pre>
</font>
</td>
</tr>
</table>
<i>
Listing 44.2: Laden einer Image-Ressource</i></p>
<p>
Diese Vorgehensweise basiert darauf, dass jede geladene Klasse ihren
<a name="ixa103268"><i>Classloader</i></a> (also das Objekt, das für
das Laden der Klasse verantwortlich war) kennt und an diesen Aufrufe
zum Laden von Ressourcen delegieren kann. Der beim Laden eines Objekts
aus einer <font color="#660099">.jar</font>-Datei verwendete Classloader
unterscheidet sich dabei sehr wohl von dem <a name="ixa103269"><i>Bootstrap Loader</i></a>,
der System- und Anwendungsklassen aus <font color="#660099">.class</font>-Dateien
lädt. Diese Unterscheidung wird in dem von <font color="#000077"><tt>getResource</tt></font>
gelieferten URL gekapselt und vom AWT-Toolkit beim Aufruf von <font color="#000077"><tt>createImage</tt></font>
aufgelöst.
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>
<p>
Nach dem Aufruf von <a href="index_c.html#ixb100644"><font color=#000080><tt>createImage</tt></font></a>
sorgt ein <a href="index_m.html#ixb101739"><font color=#000080><tt>MediaTracker</tt></font></a>
dafür, das die Bilddateien erst vollständig geladen werden,
bevor die Methode terminiert. Diese Technik verhindert, dass <font color="#000077"><tt>paint</tt></font>
aufgerufen wird, während die <font color="#000077"><tt>Image</tt></font>-Objekte
noch nicht vollständig initialisiert sind. Details dazu wurden
in <a href="k100225.html#bitmapladenanzeigen">Abschnitt 34.1.1</a>
vorgestellt.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
<tr>
<td><font color="#FFFFFF"> Hinweis </font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
</tr>
</table>
<!-- Section -->
<a name="sectlevel3id044002003"></a>
<h3>44.2.3 Eigenschaften </h3>
<p>
Wie im einleitenden Abschnitt dargelegt, sind <i>Eigenschaften</i>
ein wesentliches Designmerkmal von Beans. Eine Eigenschaft ist eigentlich
nur eine Membervariable, die über öffentliche Methoden gelesen
und geschrieben werden kann. Eine Bean kann beliebig viele Eigenschaften
haben, jede von ihnen besitzt einen Namen und einen Datentyp. Die
Bean-Designkonventionen schreiben vor, dass auf eine Eigenschaft mit
dem Namen <i>name</i> und dem Datentyp <i>typ</i> über folgende
Methoden zugegriffen werden soll:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public typ getName();
public void setName(typ newValue);
</pre>
</font>
</td>
</tr>
</table>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>
<p>
Diese beiden Methoden bezeichnet man auch als <a name="ixa103270"><i>getter-</i></a>
und <a name="ixa103271"><i>setter-Methoden</i></a>.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
<tr>
<td><font color="#FFFFFF"> Hinweis </font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
</tr>
</table>
<p>
Unsere Beispiel-Bean hat eine einzige Eigenschaft <i>lightOn</i> vom
Typ <font color="#000077"><tt>boolean</tt></font>. Ihre getter-/setter-Methoden
haben demnach folgende Signatur (der erste Buchstabe des Eigenschaftsnamens
wird großgeschrieben, da er hinter dem »get« bzw.
»set« steht):
<font color="#000077">
<pre>
public boolean getLightOn();
public void setLightOn(boolean newvalue);
</pre>
</font>
<p>
Auf diese Weise können getter- und setter-Methoden für alle
primitiven Datentypen geschrieben werden. Der GUI-Designer erkennt
Eigenschaftennamen und -typen anhand der Signaturen und stellt automatisch
einen passenden Editor dafür zur Verfügung.
<!-- Section -->
<a name="sectlevel4id044002003001"></a>
<h4>Objekte als Eigenschaften </h4>
<p>
Neben primitiven Typen ist auch die Übergabe von Objekttypen
erlaubt. Die Signaturkonventionen entsprechen genau denen von primitiven
Typen. Bei Objekteigenschaften kann allerdings nicht unbedingt davon
ausgegangen werden, dass der GUI-Designer einen geeigneten Editor
zur Verfügung stellen kann. Zwar besitzt der GUI-Designer für
die häufig benötigten Objekttypen <font color="#000077"><tt>Color</tt></font>
und <font color="#000077"><tt>Font</tt></font> standardmäßig
geeignete Editoren. Bei einem selbstdefinierten Objekttyp ist das
natürlich nicht der Fall. Hier muss der Entwickler nötigenfalls
selbst einen Editor entwickeln und dem Designer zur Verfügung
stellen. Wir werden in <a href="k100285.html#propertyeditoren">Abschnitt 44.6.2</a>
zeigen, wie das gemacht wird.
<!-- Section -->
<a name="sectlevel4id044002003002"></a>
<h4>Indizierte Eigenschaften </h4>
<p>
Anstelle eines Einzelwertes kann eine Eigenschaft auch durch ein Array
von Werten repräsentiert werden. Sie wird in diesem Fall als
<a name="ixa103272"><i>indizierte Eigenschaft</i></a> bezeichnet.
Die getter-/setter-Methoden sehen dann so aus:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public typ getName(int index);
public void setName(int index, typ newValue);
</pre>
</font>
</td>
</tr>
</table>
<p>
Es werden also keine Arrays übergeben, sondern die Methoden erwarten
jeweils den Index der gewünschten Eigenschaft als zusätzliches
Argument. Für das Einhalten der Arraygrenzen ist der Aufrufer
selbst verantwortlich. Ist die Arraygröße variabel, könnte
die Bean sie in einer zweiten Eigenschaft festhalten und über
eigene getter-/setter-Methoden verfügbar machen.
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>
<p>
Auch indizierte Eigenschaften werden vom GUI-Designer automatisch
erkannt und sollten zum Aufruf eines geeigneten Editors führen.
Die Beanbox selbst (also die von SUN zur Verfügung gestellte
Referenzimplementierung eines GUI-Designers), auf die wir in <a href="k100282.html#beanbox">Abschnitt 44.3</a>
eingehen werden, kann allerdings nicht mit indizierten Eigenschaften
umgehen.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
<tr>
<td><font color="#FFFFFF"> Hinweis </font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
</tr>
</table>
<!-- Section -->
<a name="sectlevel3id044002004"></a>
<h3>44.2.4 Implementierung </h3>
<p>
Nach diesen Vorbemerkungen ist die Implementierung der Bean zur Darstellung
der Glühbirne keine große Hürde mehr:
<a name="lightbulblisting"></a>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
<tr>
<td valign=top>
<font color="#000055">
<pre>
<font color="#555555">001 </font><font color="#00AA00">/* LightBulb.java */</font>
<font color="#555555">002 </font>
<font color="#555555">003 </font><font color="#0000AA">import</font> java.awt.*;
<font color="#555555">004 </font><font color="#0000AA">import</font> java.awt.event.*;
<font color="#555555">005 </font><font color="#0000AA">import</font> java.io.*;
<font color="#555555">006 </font><font color="#0000AA">import</font> java.beans.*;
<font color="#555555">007 </font>
<font color="#555555">008 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> LightBulb
<font color="#555555">009 </font><font color="#0000AA">extends</font> Canvas
<font color="#555555">010 </font><font color="#0000AA">implements</font> Serializable
<font color="#555555">011 </font>{
<font color="#555555">012 </font> <font color="#00AA00">//Instanzvariablen</font>
<font color="#555555">013 </font> <font color="#0000AA">protected</font> <font color="#006699">boolean</font> lighton;
<font color="#555555">014 </font> <font color="#0000AA">transient</font> <font color="#0000AA">protected</font> Image offimage;
<font color="#555555">015 </font> <font color="#0000AA">transient</font> <font color="#0000AA">protected</font> Image onimage;
<font color="#555555">016 </font>
<font color="#555555">017 </font> <font color="#00AA00">//Methoden</font>
<font color="#555555">018 </font> <font color="#0000AA">public</font> LightBulb()
<font color="#555555">019 </font> {
<font color="#555555">020 </font> lighton = <font color="#006699">false</font>;
<font color="#555555">021 </font> initTransientState();
<font color="#555555">022 </font> }
<font color="#555555">023 </font>
<font color="#555555">024 </font> <font color="#00AA00">//Getter/Setter Licht an/aus</font>
<font color="#555555">025 </font> <font color="#0000AA">public</font> <font color="#006699">void</font> setLightOn(<font color="#006699">boolean</font> on)
<font color="#555555">026 </font> {
<font color="#555555">027 </font> <font color="#0000AA">if</font> (on != <font color="#006699">this</font>.lighton) {
<font color="#555555">028 </font> <font color="#006699">this</font>.lighton = on;
<font color="#555555">029 </font> repaint();
<font color="#555555">030 </font> }
<font color="#555555">031 </font> }
<font color="#555555">032 </font>
<font color="#555555">033 </font> <font color="#0000AA">public</font> <font color="#006699">boolean</font> getLightOn()
<font color="#555555">034 </font> {
<font color="#555555">035 </font> <font color="#0000AA">return</font> <font color="#006699">this</font>.lighton;
<font color="#555555">036 </font> }
<font color="#555555">037 </font>
<font color="#555555">038 </font> <font color="#0000AA">public</font> <font color="#006699">void</font> toggleLight()
<font color="#555555">039 </font> {
<font color="#555555">040 </font> setLightOn(!getLightOn());
<font color="#555555">041 </font> }
<font color="#555555">042 </font>
<font color="#555555">043 </font> <font color="#00AA00">//Implementierung der Oberfläche</font>
<font color="#555555">044 </font> <font color="#0000AA">public</font> <font color="#006699">void</font> paint(Graphics g)
<font color="#555555">045 </font> {
<font color="#555555">046 </font> <font color="#006699">int</font> width = getSize().width;
<font color="#555555">047 </font> <font color="#006699">int</font> height = getSize().height;
<font color="#555555">048 </font> <font color="#006699">int</font> xpos = 0;
<font color="#555555">049 </font> <font color="#0000AA">if</font> (width > 40) {
<font color="#555555">050 </font> xpos = (width - 40) / 2;
<font color="#555555">051 </font> }
<font color="#555555">052 </font> <font color="#006699">int</font> ypos = 0;
<font color="#555555">053 </font> <font color="#0000AA">if</font> (height > 40) {
<font color="#555555">054 </font> ypos = (height - 40) / 2;
<font color="#555555">055 </font> }
<font color="#555555">056 </font> g.drawImage(
<font color="#555555">057 </font> (<font color="#006699">this</font>.lighton ? onimage : offimage),
<font color="#555555">058 </font> xpos,
<font color="#555555">059 </font> ypos,
<font color="#555555">060 </font> <font color="#006699">this</font>
<font color="#555555">061 </font> );
<font color="#555555">062 </font> }
<font color="#555555">063 </font>
<font color="#555555">064 </font> <font color="#0000AA">public</font> Dimension getPreferredSize()
<font color="#555555">065 </font> {
<font color="#555555">066 </font> <font color="#0000AA">return</font> <font color="#0000AA">new</font> Dimension(40, 40);
<font color="#555555">067 </font> }
<font color="#555555">068 </font>
<font color="#555555">069 </font> <font color="#0000AA">public</font> Dimension getMinimumSize()
<font color="#555555">070 </font> {
<font color="#555555">071 </font> <font color="#0000AA">return</font> <font color="#0000AA">new</font> Dimension(40, 40);
<font color="#555555">072 </font> }
<font color="#555555">073 </font>
<font color="#555555">074 </font> <font color="#00AA00">//Private Methoden</font>
<font color="#555555">075 </font> <font color="#0000AA">private</font> <font color="#006699">void</font> initTransientState()
<font color="#555555">076 </font> {
<font color="#555555">077 </font> offimage = getImageResource(<font color="#0000FF">"bulb1.gif"</font>);
<font color="#555555">078 </font> onimage = getImageResource(<font color="#0000FF">"bulb2.gif"</font>);
<font color="#555555">079 </font> }
<font color="#555555">080 </font>
<font color="#555555">081 </font> <font color="#0000AA">private</font> <font color="#006699">void</font> readObject(ObjectInputStream stream)
<font color="#555555">082 </font> <font color="#0000AA">throws</font> IOException, ClassNotFoundException
<font color="#555555">083 </font> {
<font color="#555555">084 </font> stream.defaultReadObject();
<font color="#555555">085 </font> initTransientState();
<font color="#555555">086 </font> }
<font color="#555555">087 </font>
<font color="#555555">088 </font> <font color="#0000AA">private</font> Image getImageResource(String name)
<font color="#555555">089 </font> {
<font color="#555555">090 </font> Image img = <font color="#006699">null</font>;
<font color="#555555">091 </font> <font color="#0000AA">try</font> {
<font color="#555555">092 </font> java.net.URL url = getClass().getResource(name);
<font color="#555555">093 </font> img = getToolkit().createImage(url);
<font color="#555555">094 </font> } <font color="#0000AA">catch</font> (Exception e) {
<font color="#555555">095 </font> System.err.println(e.toString());
<font color="#555555">096 </font> }
<font color="#555555">097 </font> <font color="#0000AA">return</font> img;
<font color="#555555">098 </font> }
<font color="#555555">099 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/LightBulb.java"><font color="#000055" size=-1>LightBulb.java</font></a></td>
</tr>
</table>
<i>
Listing 44.3: Die Bean zur Anzeige einer Glühbirne</i></p>
<p>
Der Konstruktor initialisiert zunächst die Zustandsvariable <font color="#000077"><tt>lighton</tt></font>
und ruft dann die Methode <font color="#000077"><tt>initTransientState</tt></font>
auf, um die beiden gif-Dateien zu laden. Durch Aufruf von <font color="#000077"><tt>setLightOn</tt></font>
kann die Beleuchtung wahlweise an- oder ausgeschaltet werden; <font color="#000077"><tt>getLightOn</tt></font>
liefert den aktuellen Zustand. In <font color="#000077"><tt>paint</tt></font>
wird - abhängig vom aktuellen Zustand - jeweils eines der beiden
Images ausgegeben. Die Umrechnungsroutinen dienen dazu, die Images
zentriert auszugeben, wenn mehr Platz als nötig zur Verfügung
steht.
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>
<p>
Bemerkenswert ist, dass die Methode <a href="index_r.html#ixb102215"><font color=#000080><tt>readObject</tt></font></a>
überlagert wurde. Sie wird immer dann aufgerufen, wenn die zuvor
serialisierte Bean per Deserialisierung instanziert wird. In diesem
Fall würde nämlich der Konstruktor des Objekts gar nicht
aufgerufen werden (siehe <a href="k100261.html#lesenvonobjekten">Abschnitt 41.1.3</a>)
und die <font color="#000077"><tt>Image</tt></font>-Variablen blieben
uninitialisiert. Ihre Initialisierung haben wir deshalb in die Methode
<font color="#000077"><tt>initTransientState</tt></font> verlagert,
die sowohl aus dem Konstruktor als auch aus <font color="#000077"><tt>readObject</tt></font>
aufgerufen wird. Damit wird die Bean in beiden Fällen (Instanzierung
per <font color="#000077"><tt>new</tt></font> und Deserialisierung)
vollständig initialisiert. In seiner eigentlichen Funktion ruft
<font color="#000077"><tt>readObject</tt></font> lediglich <a name="ixa103273"><a href="index_d.html#ixb102417"><font color=#000080><tt>defaultReadObject</tt></font></a></a>
auf, um die Standard-Deserialisierung auszuführen.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
<tr>
<td><font color="#FFFFFF"> Hinweis </font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
</tr>
</table>
<!-- Section -->
<a name="sectlevel3id044002005"></a>
<h3>44.2.5 Verwendung der Bean </h3>
<p>
Zum Abschluss wollen wir uns ansehen, wie die erstellte Bean in ein
einfaches Programm eingebunden werden kann. Dazu bedienen wir uns
exakt der Techniken, die bereits in den Kapiteln <a href="k100201.html#kapitelguidialoge">31</a>
bis <a href="k100224.html#kapitelbitmapsanimationen">34</a> beschrieben
wurden. Tatsächlich unterscheidet sich die Verwendung einer selbstentwickelten
Bean nicht vom Einbinden einer vordefinierten Komponente.
<a name="listingid044004"></a>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
<tr>
<td valign=top>
<font color="#000055">
<pre>
<font color="#555555">001 </font><font color="#00AA00">/* Listing4404.java */</font>
<font color="#555555">002 </font>
<font color="#555555">003 </font><font color="#0000AA">import</font> java.awt.*;
<font color="#555555">004 </font><font color="#0000AA">import</font> java.awt.event.*;
<font color="#555555">005 </font>
<font color="#555555">006 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing4404
<font color="#555555">007 </font><font color="#0000AA">extends</font> Frame
<font color="#555555">008 </font>{
<font color="#555555">009 </font> <font color="#0000AA">public</font> Listing4404()
<font color="#555555">010 </font> {
<font color="#555555">011 </font> <font color="#006699">super</font>(<font color="#0000FF">"Bean einbinden"</font>);
<font color="#555555">012 </font> setLayout(<font color="#0000AA">new</font> FlowLayout());
<font color="#555555">013 </font> setBackground(Color.lightGray);
<font color="#555555">014 </font> LightBulb bulb1 = <font color="#0000AA">new</font> LightBulb();
<font color="#555555">015 </font> bulb1.setLightOn(<font color="#006699">false</font>);
<font color="#555555">016 </font> add(bulb1);
<font color="#555555">017 </font> LightBulb bulb2 = <font color="#0000AA">new</font> LightBulb();
<font color="#555555">018 </font> bulb2.setLightOn(<font color="#006699">true</font>);
<font color="#555555">019 </font> add(bulb2);
<font color="#555555">020 </font> addWindowListener(
<font color="#555555">021 </font> <font color="#0000AA">new</font> WindowAdapter() {
<font color="#555555">022 </font> <font color="#0000AA">public</font> <font color="#006699">void</font> windowClosing(WindowEvent event)
<font color="#555555">023 </font> {
<font color="#555555">024 </font> System.exit(0);
<font color="#555555">025 </font> }
<font color="#555555">026 </font> }
<font color="#555555">027 </font> );
<font color="#555555">028 </font> }
<font color="#555555">029 </font>
<font color="#555555">030 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
<font color="#555555">031 </font> {
<font color="#555555">032 </font> Listing4404 frm = <font color="#0000AA">new</font> Listing4404();
<font color="#555555">033 </font> frm.setLocation(100, 100);
<font color="#555555">034 </font> frm.pack();
<font color="#555555">035 </font> frm.setVisible(<font color="#006699">true</font>);
<font color="#555555">036 </font> }
<font color="#555555">037 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Listing4404.java"><font color="#000055" size=-1>Listing4404.java</font></a></td>
</tr>
</table>
<i>
Listing 44.4: Einbinden einer einfachen Bean</i></p>
<p>
Die Ausgabe des Programms sieht wie folgt aus:
<p>
<a name="imageid044001"></a>
<img src="images/BulbTest1.gif">
<p>
<p><i>
Abbildung 44.1: Die Glühlampen-Bean</i></p>
<hr>
<table border=0 cellpadding=0 cellspacing=1 width="100%">
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html"> Titel </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </a>
<td align="right">Handbuch der Java-Programmierung, 5. Auflage, Addison
Wesley, Version 5.0.1
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100279.html"> << </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100280.html"> < </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100282.html"> > </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100287.html"> >> </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </a>
<td align="right">© 1998, 2007 Guido Krüger & Thomas
Stark, <a href="http://www.javabuch.de">http://www.javabuch.de</a>
</table>
<a name="endofbody"></a>
</body>
</html>
|