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
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
|
<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,k100243.html;106,k100244.html;107,k100246.html;108,k100248.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="k100243.html"> << </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100244.html"> < </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100246.html"> > </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100248.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 38 - Swing: Komponenten II
</table>
<hr>
<!-- Section -->
<a name="sectlevel2id038002"></a>
<h2>38.2 JTable </h2>
<hr>
<ul>
<li><a href="k100245.html#sectlevel2id038002">38.2 JTable</a>
<ul>
<li><a href="k100245.html#sectlevel3id038002001">38.2.1 Erzeugen von Tabellen</a>
<li><a href="k100245.html#sectlevel3id038002002">38.2.2 Konfiguration der Tabelle</a>
<li><a href="k100245.html#sectlevel3id038002003">38.2.3 Selektieren von Elementen</a>
<ul>
<li><a href="k100245.html#sectlevel4id038002003001">Selektionsmodi</a>
<li><a href="k100245.html#sectlevel4id038002003002">Abfragen der Selektion</a>
<li><a href="k100245.html#sectlevel4id038002003003">Verändern der Selektion</a>
</ul>
<li><a href="k100245.html#sectlevel3id038002004">38.2.4 Zugriff auf den Inhalt der Tabelle</a>
<ul>
<li><a href="k100245.html#sectlevel4id038002004001">Die Daten in der Tabelle</a>
<li><a href="k100245.html#sectlevel4id038002004002">Editieren von Tabellenelementen</a>
</ul>
<li><a href="k100245.html#sectlevel3id038002005">38.2.5 Das Tabellenmodell</a>
<ul>
<li><a href="k100245.html#sectlevel4id038002005001">Beispiel</a>
</ul>
<li><a href="k100245.html#sectlevel3id038002006">38.2.6 Das Spaltenmodell</a>
<li><a href="k100245.html#sectlevel3id038002007">38.2.7 Rendering der Zellen</a>
<li><a href="k100245.html#sectlevel3id038002008">38.2.8 Reaktion auf Ereignisse</a>
</ul>
</ul>
<hr>
<!-- Section -->
<a name="sectlevel3id038002001"></a>
<h3>38.2.1 Erzeugen von Tabellen </h3>
<p>
Eines der in anspruchsvollen Benutzeroberflächen am häufigsten
gebrauchten Dialogelemente ist die <i>Tabelle</i>, also eine mehrzeilige,
mehrspaltige Darstellung von Daten. Diese im AWT fehlende Komponente
wird in Swing durch die Klasse <a name="ixa102749"><a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a></a>
zur Verfügung gestellt. Mit ihrer Hilfe lassen sich unterschiedlichste
Arten von textuellen oder grafischen Daten tabellarisch darstellen
und editieren. Das Programm hat dabei weitreichende Möglichkeiten,
die Tabelle zu konfigurieren, ihren Inhalt anzupassen und auf Benutzerereignisse
zu reagieren.
<p>
Die wichtigsten Konstruktoren von <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
sind:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public JTable(Object[][] rowData, Object[] columnNames)
public JTable(Vector rowData, Vector columnNames)
public JTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></td>
</tr>
</table>
<p>
An den ersten Konstruktor werden die darzustellenden Daten in Form
eines zweidimensionalen Arrays übergeben. Dessen erste Dimension
enthält die Zeilen, die zweite die Spalten. Zur Darstellung in
der Tabelle werden die Array-Elemente mit <a href="index_t.html#ixb100327"><font color=#000080><tt>toString</tt></font></a>
in Strings umgewandelt. Das zweite Argument enthält ein Array
mit Strings, die als Spaltenköpfe angezeigt werden.
<p>
Statt der Übergabe von Arrays kann auch der zweite Konstruktor
verwendet und die Daten und Spaltenköpfe in einem <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>
übergeben werden. In diesem Fall muss der Datenvektor <font color="#000077"><tt>rowData</tt></font>
für jede Zeile einen Untervektor mit den Datenelementen dieser
Zeile enthalten.
<p>
Der dritte Konstruktor stellt die allgemeinste Möglichkeit dar,
eine <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
zu konstruieren. Hierbei werden alle drei Modelle der Tabelle explizit
an den Konstruktor übergeben. Das <a name="ixa102750"><a href="index_t.html#ixb102032"><font color=#000080><tt>TableModel</tt></font></a></a>
stellt dabei die Daten zur Verfügung, das <a name="ixa102751"><a href="index_t.html#ixb102033"><font color=#000080><tt>TableColumnModel</tt></font></a></a>
definiert die Spalten, und das <a name="ixa102752"><a href="index_l.html#ixb101947"><font color=#000080><tt>ListSelectionModel</tt></font></a></a>
ist für die Selektion von Tabellenelementen zuständig. Werden
alle drei Modelle separat instanziert und übergeben, hat das
Programm die volle Kontrolle über alle Aspekte der Tabellendarstellung
und -verarbeitung.
<p>
Eine einfache Tabelle läßt sich also sehr schnell erzeugen:
<a name="jtableexample1"></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">/* Listing3804.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> javax.swing.*;
<font color="#555555">006 </font>
<font color="#555555">007 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing3804
<font color="#555555">008 </font><font color="#0000AA">extends</font> JFrame
<font color="#555555">009 </font><font color="#0000AA">implements</font> TableData
<font color="#555555">010 </font>{
<font color="#555555">011 </font> <font color="#0000AA">public</font> Listing3804()
<font color="#555555">012 </font> {
<font color="#555555">013 </font> <font color="#006699">super</font>(<font color="#0000FF">"JTable 1"</font>);
<font color="#555555">014 </font> addWindowListener(<font color="#0000AA">new</font> WindowClosingAdapter(<font color="#006699">true</font>));
<font color="#555555">015 </font> JTable table = <font color="#0000AA">new</font> JTable(DATA, COLHEADS);
<font color="#555555">016 </font> Container cp = getContentPane();
<font color="#555555">017 </font> cp.add(<font color="#0000AA">new</font> JLabel(<font color="#0000FF">"Alte c\'t-Ausgaben:"</font>), BorderLayout.NORTH);
<font color="#555555">018 </font> cp.add(<font color="#0000AA">new</font> JScrollPane(table), BorderLayout.CENTER);
<font color="#555555">019 </font> }
<font color="#555555">020 </font>
<font color="#555555">021 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
<font color="#555555">022 </font> {
<font color="#555555">023 </font> Listing3804 frame = <font color="#0000AA">new</font> Listing3804();
<font color="#555555">024 </font> frame.setLocation(100, 100);
<font color="#555555">025 </font> frame.setSize(300, 200);
<font color="#555555">026 </font> frame.setVisible(<font color="#006699">true</font>);
<font color="#555555">027 </font> }
<font color="#555555">028 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Listing3804.java"><font color="#000055" size=-1>Listing3804.java</font></a></td>
</tr>
</table>
<i>
Listing 38.4: Eine einfache Tabelle</i></p>
<p>
Die Ausgabe des Programms ist:
<p>
<a name="imageid038005"></a>
<img src="images/JTable1.gif">
<p>
<p><i>
Abbildung 38.5: Eine einfache Tabelle</i></p>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=1></td>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>
<p>
Wie in anderen großen Dialogelementen haben wir die <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
vor der Übergabe an ihren GUI-Container in eine <a href="index_j.html#ixb101779"><font color=#000080><tt>JScrollPane</tt></font></a>
verpackt. Neben dem Effekt, die Daten vertikal oder horizontal scrollen
zu können, hat das vor allem zur Folge, dass die Spaltenköpfe
angezeigt werden. Ohne <a href="index_j.html#ixb101779"><font color=#000080><tt>JScrollPane</tt></font></a>
wären sie dagegen nicht sichtbar.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#CC0000">
<tr>
<td><font color="#FFFFFF"> Warnung </font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
</tr>
</table>
<p>
In <a href="k100245.html#jtableexample1">Listing 38.4</a> wurden zwei
Konstanten <font color="#000077"><tt>DATA</tt></font> und <font color="#000077"><tt>COLHEADS</tt></font>
verwendet. Sie dienen als Beispieldaten für die Programme dieses
Abschnitts und wurden als Konstanten in dem Interface <font color="#000077"><tt>TableData</tt></font>
definiert:
<a name="listingid038005"></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">/* TableData.java */</font>
<font color="#555555">002 </font>
<font color="#555555">003 </font><font color="#0000AA">public</font> <font color="#0000AA">interface</font> TableData
<font color="#555555">004 </font>{
<font color="#555555">005 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#0000AA">final</font> String[][] DATA = {
<font color="#555555">006 </font> {<font color="#0000FF">" 1/1987"</font>, <font color="#0000FF">"195"</font>, <font color="#0000FF">"Vergleichstest EGA-Karten"</font>},
<font color="#555555">007 </font> {<font color="#0000FF">" 2/1987"</font>, <font color="#0000FF">"171"</font>, <font color="#0000FF">"Schneider PC: Bewährungsprobe"</font>},
<font color="#555555">008 </font> {<font color="#0000FF">" 3/1987"</font>, <font color="#0000FF">"235"</font>, <font color="#0000FF">"Luxus-Textsyteme im Vergleich"</font>},
<font color="#555555">009 </font> {<font color="#0000FF">" 4/1987"</font>, <font color="#0000FF">"195"</font>, <font color="#0000FF">"Turbo BASIC"</font>},
<font color="#555555">010 </font> {<font color="#0000FF">" 5/1987"</font>, <font color="#0000FF">"211"</font>, <font color="#0000FF">"640-K-Grenze durchbrochen"</font>},
<font color="#555555">011 </font> {<font color="#0000FF">" 6/1987"</font>, <font color="#0000FF">"211"</font>, <font color="#0000FF">"Expertensysteme"</font>},
<font color="#555555">012 </font> {<font color="#0000FF">" 7/1987"</font>, <font color="#0000FF">"199"</font>, <font color="#0000FF">"IBM Model 30 im Detail"</font>},
<font color="#555555">013 </font> {<font color="#0000FF">" 8/1987"</font>, <font color="#0000FF">"211"</font>, <font color="#0000FF">"PAK-68: Tuning für 68000er"</font>},
<font color="#555555">014 </font> {<font color="#0000FF">" 9/1987"</font>, <font color="#0000FF">"215"</font>, <font color="#0000FF">"Desktop Publishing"</font>},
<font color="#555555">015 </font> {<font color="#0000FF">"10/1987"</font>, <font color="#0000FF">"279"</font>, <font color="#0000FF">"2,5 MByte im ST"</font>},
<font color="#555555">016 </font> {<font color="#0000FF">"11/1987"</font>, <font color="#0000FF">"279"</font>, <font color="#0000FF">"Transputer-Praxis"</font>},
<font color="#555555">017 </font> {<font color="#0000FF">"12/1987"</font>, <font color="#0000FF">"271"</font>, <font color="#0000FF">"Preiswert mit 24 Nadeln"</font>},
<font color="#555555">018 </font> {<font color="#0000FF">" 1/1988"</font>, <font color="#0000FF">"247"</font>, <font color="#0000FF">"Schnelle 386er"</font>},
<font color="#555555">019 </font> {<font color="#0000FF">" 2/1988"</font>, <font color="#0000FF">"231"</font>, <font color="#0000FF">"Hayes-kompatible Modems"</font>},
<font color="#555555">020 </font> {<font color="#0000FF">" 3/1988"</font>, <font color="#0000FF">"295"</font>, <font color="#0000FF">"TOS/GEM auf 68020"</font>},
<font color="#555555">021 </font> {<font color="#0000FF">" 4/1988"</font>, <font color="#0000FF">"263"</font>, <font color="#0000FF">"Projekt Super-EGA"</font>},
<font color="#555555">022 </font> {<font color="#0000FF">" 5/1988"</font>, <font color="#0000FF">"263"</font>, <font color="#0000FF">"Neuheiten auf der CeBIT 88"</font>},
<font color="#555555">023 </font> {<font color="#0000FF">" 6/1988"</font>, <font color="#0000FF">"231"</font>, <font color="#0000FF">"9600-Baud-Modem am Postnetz"</font>}
<font color="#555555">024 </font> };
<font color="#555555">025 </font>
<font color="#555555">026 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#0000AA">final</font> String[] COLHEADS = {
<font color="#555555">027 </font> <font color="#0000FF">"Ausgabe"</font>, <font color="#0000FF">"Seiten"</font>, <font color="#0000FF">"Titelthema"</font>
<font color="#555555">028 </font> };
<font color="#555555">029 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/TableData.java"><font color="#000055" size=-1>TableData.java</font></a></td>
</tr>
</table>
<i>
Listing 38.5: Das Interface TableData</i></p>
<p>
Auf diese Weise können die Daten in den folgenden Beispielen
dieses Abschnitts einfach mit der Anweisung <font color="#000077"><tt>implements
TableData</tt></font> importiert und dem Programm zur Verfügung
gestellt werden. Diese - auf den ersten Blick - etwas ungewöhnliche
Verwendung eines Interfaces ist ein Standard-Idiom in Java und wurde
in <a href="k100061.html#konstininterfaces">Abschnitt 9.4.1</a> erläutert.
<!-- Section -->
<a name="sectlevel3id038002002"></a>
<h3>38.2.2 Konfiguration der Tabelle </h3>
<p>
Eine <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
läßt sich auf vielfältige Weise konfigurieren. Mit
<a name="ixa102753"><a href="index_s.html#ixb102034"><font color=#000080><tt>setRowHeight</tt></font></a></a>
wird die Gesamthöhe einer Zeile festgelegt, alle Zeilen sind
dabei gleich hoch. Mit <a name="ixa102754"><a href="index_s.html#ixb102035"><font color=#000080><tt>setRowMargin</tt></font></a></a>
wird der am oberen und unteren Rand jeder Zelle freibleibende Platz
bestimmt. Der für den Inhalt der Zelle verfügbare Platz
ergibt sich aus der Zellenhöhe minus oberem und unterem Rand.
Durch Aufruf von <a name="ixa102755"><a href="index_s.html#ixb102036"><font color=#000080><tt>setIntercellSpacing</tt></font></a></a>
kann (zusammen mit dem vertikalen) auch der horizontale Rand der Zellenelemente
festgelegt werden:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public void setRowHeight(int newHeight)
public void setRowMargin(int rowMargin)
public void setIntercellSpacing(Dimension newSpacing)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></td>
</tr>
</table>
<p>
Standardmäßig werden die Zellen einer <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
mit senkrechten und waagerechten Begrenzungslinien voneinander getrennt.
Mit <a name="ixa102756"><a href="index_s.html#ixb102037"><font color=#000080><tt>setShowGrid</tt></font></a></a>
können beide Linienarten zugleich an- oder ausgeschaltet werden.
Sollen die horizontalen oder vertikalen Linien separat aktiviert oder
deaktiviert werden, können die Methoden <a name="ixa102757"><a href="index_s.html#ixb102038"><font color=#000080><tt>setShowHorizontalLines</tt></font></a></a>
und <a name="ixa102758"><a href="index_s.html#ixb102039"><font color=#000080><tt>setShowVerticalLines</tt></font></a></a>
verwendet werden:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public void setShowGrid(boolean b)
public void setShowHorizontalLines(boolean b)
public void setShowVerticalLines(boolean b)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></td>
</tr>
</table>
<p>
Das Verändern der Farben der Zellen ist in begrenzter Weise mit
folgenden Methoden möglich:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public void setGridColor(Color newColor)
public void setSelectionForeground(Color selectionForeground)
public void setSelectionBackground(Color selectionBackground)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></td>
</tr>
</table>
<p>
<a name="ixa102759"><a href="index_s.html#ixb102040"><font color=#000080><tt>setGridColor</tt></font></a></a>
verändert die Farbe, in der die Gitterlinien angezeigt werden.
Mit <a name="ixa102760"><a href="index_s.html#ixb102041"><font color=#000080><tt>setSelectionForeground</tt></font></a></a>
und <a name="ixa102761"><a href="index_s.html#ixb102042"><font color=#000080><tt>setSelectionBackground</tt></font></a></a>
wird die Vorder- und Hintergrundfarbe des selektierten Bereichs festgelegt.
<p>
Als letzte der Konfigurationsmethoden wollen wir uns <a name="ixa102762"><a href="index_s.html#ixb102043"><font color=#000080><tt>setAutoResizeMode</tt></font></a></a>
ansehen:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public void setAutoResizeMode(int mode)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></td>
</tr>
</table>
<p>
Sie bestimmt das Verhalten der Tabelle, nachdem die Breite einer einzelnen
Spalte verändert wurde. Der dadurch freiwerdende oder zusätzlich
benötigte Platz kann nämlich auf unterschiedliche Weise
den übrigen Spalten zugeordnet werden. Der Parameter <font color="#000077"><tt>mode</tt></font>
kann folgende Werte annehmen: <a name="tableid038002"></a>
<p>
<table cols=2 border width=66%>
<tr>
<td valign=top align=left width=25%><b>Modus</b></td>
<td valign=top align=left width=75%><b>Bedeutung</b></td></tr>
<tr>
<td valign=top align=left><a name="ixa102763"><a href="index_a.html#ixb102044"><font color=#000080><tt>AUTO_RESIZE_OFF</tt></font></a></a></td>
<td valign=top align=left>Es erfolgt keine automatische Größenanpassung
der übrigen Spalten. Wurde die Tabelle in <a href="index_j.html#ixb101779"><font color=#000080><tt>JScrollPane</tt></font></a>
verpackt, bekommt sie nötigenfalls einen horizontalen Schieberegler.</td></tr>
<tr>
<td valign=top align=left><a name="ixa102764"><a href="index_a.html#ixb102045"><font color=#000080><tt>AUTO_RESIZE_LAST_COLUMN</tt></font></a></a></td>
<td valign=top align=left>Die letzte Spalte wird zum Größenausgleich
verwendet. Dadurch reduziert sich der Platz für die letzte Spalte,
wenn eine andere Spalte vergrößert wird, und er erhöht
sich, wenn sie verkleinert wird.</td></tr>
<tr>
<td valign=top align=left><a name="ixa102765"><a href="index_a.html#ixb102046"><font color=#000080><tt>AUTO_RESIZE_NEXT_COLUMN</tt></font></a></a></td>
<td valign=top align=left>Die rechts neben der modifizierten Spalte
liegende Spalte wird zum Größenausgleich verwendet.</td></tr>
<tr>
<td valign=top align=left><a name="ixa102766"><a href="index_a.html#ixb102047"><font color=#000080><tt>AUTO_RESIZE_SUBSEQUENT_COLUMNS</tt></font></a></a></td>
<td valign=top align=left>Die Größenänderung wird
gleichmäßig auf alle nachfolgenden Spalten verteilt.</td></tr>
<tr>
<td valign=top align=left><a name="ixa102767"><a href="index_a.html#ixb102048"><font color=#000080><tt>AUTO_RESIZE_ALL_COLUMNS</tt></font></a></a></td>
<td valign=top align=left>Die Größenänderung wird
auf alle Spalten der Tabelle verteilt.</td></tr>
</table>
<p><i>
Tabelle 38.2: Parameter für setAutoResizeMode</i></p>
<!-- Section -->
<a name="sectlevel3id038002003"></a>
<h3>38.2.3 Selektieren von Elementen </h3>
<!-- Section -->
<a name="sectlevel4id038002003001"></a>
<h4>Selektionsmodi </h4>
<p>
Die Elemente einer <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
können auf unterschiedliche Weise selektiert werden. Welche Möglichkeiten
der Selektion dem Anwender zur Verfügung gestellt werden, regeln
die folgenden Methoden:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public void setRowSelectionAllowed(boolean flag)
public void setColumnSelectionAllowed(boolean flag)
public void setSelectionMode(int selectionMode)
public void setCellSelectionEnabled(boolean flag)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></td>
</tr>
</table>
<p>
Soll zeilenweise selektiert werden, ist <a name="ixa102768"><a href="index_s.html#ixb102049"><font color=#000080><tt>setRowSelectionAllowed</tt></font></a></a>
mit <a href="index_t.html#ixb100233"><font color=#000080><tt>true</tt></font></a>
als Argument aufzurufen. Soll spaltenweise selektiert werden, ist
analog <a name="ixa102769"><a href="index_s.html#ixb102050"><font color=#000080><tt>setColumnSelectionAllowed</tt></font></a></a>
aufzurufen. Durch Übergabe von <a href="index_f.html#ixb100234"><font color=#000080><tt>false</tt></font></a>
können beide Selektionsarten ausgeschaltet werden und nur noch
einzelne Zellen selektiert werden. Standardmäßig kann zeilen-,
aber nicht spaltenweise selektiert werden.
<p>
Mit <a name="ixa102770"><a href="index_s.html#ixb101946"><font color=#000080><tt>setSelectionMode</tt></font></a></a>
wird festgelegt, ob ein einzelnes Element, ein zusammenhängender
Bereich oder mehrere Bereiche selektiert werden können. Hier
ist eine der in <a href="k100240.html#jlist">Abschnitt 37.3.1</a>
beschriebenen Konstanten <a name="ixa102771"><a href="index_s.html#ixb101948"><font color=#000080><tt>SINGLE_SELECTION</tt></font></a></a>,
<a name="ixa102772"><a href="index_s.html#ixb101949"><font color=#000080><tt>SINGLE_INTERVAL_SELECTION</tt></font></a></a>
oder <a name="ixa102773"><a href="index_m.html#ixb101950"><font color=#000080><tt>MULTIPLE_INTERVAL_SELECTION</tt></font></a></a>
der Klasse <a name="ixa102774"><a href="index_l.html#ixb101947"><font color=#000080><tt>ListSelectionModel</tt></font></a></a>
zu übergeben. Wird <a name="ixa102775"><a href="index_s.html#ixb102051"><font color=#000080><tt>setCellSelectionEnabled</tt></font></a></a>
mit <a href="index_t.html#ixb100233"><font color=#000080><tt>true</tt></font></a>
als Argument aufgerufen, können Zeilen und Spalten gleichzeitig
markiert und so zusammenhängende rechteckige Bereiche von Zellen
(einschließlich einer einzelnen) selektiert werden.
<!-- Section -->
<a name="sectlevel4id038002003002"></a>
<h4>Abfragen der Selektion </h4>
<p>
Um herauszufinden, welche Elemente selektiert wurden, können
folgende Methoden verwendet werden:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public int getSelectedRow()
public int getSelectedColumn()
public int[] getSelectedRows()
public int[] getSelectedColumns()
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></td>
</tr>
</table>
<p>
<a name="ixa102776"><a href="index_g.html#ixb102052"><font color=#000080><tt>getSelectedRow</tt></font></a></a>
und <a name="ixa102777"><a href="index_g.html#ixb102053"><font color=#000080><tt>getSelectedColumn</tt></font></a></a>
liefern die selektierte Zeile bzw. Spalte, wenn der Selektionsmodus
<a href="index_s.html#ixb101948"><font color=#000080><tt>SINGLE_SELECTION</tt></font></a>
ist. Die erste Zeile und Spalte haben dabei jeweils den Index 0. Erlaubt
der aktuelle Selektionsmodus das Selektieren ganzer Zeilen oder Spalten,
impliziert das Ergebnis, dass <i>alle</i> Elemente dieser Zeile bzw.
Spalte selektiert sind. Ist einer der Mehrfachselektionsmodi aktiviert,
können mit <a name="ixa102778"><a href="index_g.html#ixb102054"><font color=#000080><tt>getSelectedRows</tt></font></a></a>
und <a name="ixa102779"><a href="index_g.html#ixb102055"><font color=#000080><tt>getSelectedColumns</tt></font></a></a>
Arrays mit allen selektierten Zeilen und Spalten beschafft werden.
<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>
Falls keine Elemente selektiert sind, geben <a href="index_g.html#ixb102052"><font color=#000080><tt>getSelectedRow</tt></font></a>
und <a href="index_g.html#ixb102053"><font color=#000080><tt>getSelectedColumn</tt></font></a>
-1 und <a href="index_g.html#ixb102054"><font color=#000080><tt>getSelectedRows</tt></font></a>
und <a href="index_g.html#ixb102055"><font color=#000080><tt>getSelectedColumns</tt></font></a>
ein leeres Array zurück.</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="sectlevel4id038002003003"></a>
<h4>Verändern der Selektion </h4>
<p>
<a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
stellt auch Methoden zur Verfügung, mit denen die Selektion programmgesteuert
verändert werden kann:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public void selectAll()
public void clearSelection()
public void setRowSelectionInterval(int index0, int index1)
public void addRowSelectionInterval(int index0, int index1)
public void removeRowSelectionInterval(int index0, int index1)
public void setColumnSelectionInterval(int index0, int index1)
public void addColumnSelectionInterval(int index0, int index1)
public void removeColumnSelectionInterval(int index0, int index1)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></td>
</tr>
</table>
<p>
Mit <a name="ixa102780"><a href="index_s.html#ixb101656"><font color=#000080><tt>selectAll</tt></font></a></a>
kann die komplette Tabelle markiert werden, mit <a name="ixa102781"><a href="index_c.html#ixb101959"><font color=#000080><tt>clearSelection</tt></font></a></a>
wird die Selektion entfernt. Mit <a name="ixa102782"><a href="index_s.html#ixb102056"><font color=#000080><tt>setRowSelectionInterval</tt></font></a></a>
kann ein zusammenhängender Bereich von Zeilen markiert werden.
Mit <a name="ixa102783"><a href="index_a.html#ixb102057"><font color=#000080><tt>addRowSelectionInterval</tt></font></a></a>
wird ein solcher zur aktuellen Selektion hinzugefügt und mit
<a name="ixa102784"><a href="index_r.html#ixb102058"><font color=#000080><tt>removeRowSelectionInterval</tt></font></a></a>
daraus entfernt. Für die Selektion von Spalten stehen die analogen
Methoden <a name="ixa102785"><a href="index_s.html#ixb102059"><font color=#000080><tt>setColumnSelectionInterval</tt></font></a></a>,
<a name="ixa102786"><a href="index_a.html#ixb102060"><font color=#000080><tt>addColumnSelectionInterval</tt></font></a></a>
und <a name="ixa102787"><a href="index_r.html#ixb102061"><font color=#000080><tt>removeColumnSelectionInterval</tt></font></a></a>
zur Verfügung.
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=1></td>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>
<p>
Damit die beschriebenen Methoden korrekt funktionieren, sollte ihr
Aufruf in Einklang mit den aktuell gewählten Selektionsmodi stehen.
Im RC1 des JDK 1.3 gab es beispielsweise Probleme, wenn <a href="index_s.html#ixb101656"><font color=#000080><tt>selectAll</tt></font></a>
auf einer Tabelle aufgerufen wurde, die nur Einfachselektion erlaubte.
Nach dem Aufruf wurde zwar (korrekterweise) keine Selektion mehr angezeigt,
die Methoden zur Abfrage der selektierten Elemente verhielten sich
aber dennoch so, als wären alle Elemente selektiert. Bei Verwendung
von <a href="index_a.html#ixb102057"><font color=#000080><tt>addRowSelectionInterval</tt></font></a>
fiel dagegen auf, dass die Methode nur dann korrekt funktionierte,
wenn der Selektionsmodus <a href="index_m.html#ixb101950"><font color=#000080><tt>MULTIPLE_INTERVAL_SELECTION</tt></font></a>
aktiviert war.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#CC0000">
<tr>
<td><font color="#FFFFFF"> Warnung </font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
</tr>
</table>
<!-- Section -->
<a name="sectlevel3id038002004"></a>
<h3>38.2.4 Zugriff auf den Inhalt der Tabelle </h3>
<!-- Section -->
<a name="sectlevel4id038002004001"></a>
<h4>Die Daten in der Tabelle </h4>
<p>
Unabhängig von der aktuellen Selektion kann natürlich auch
auf den Inhalt der Tabelle zugegriffen werden:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public int getRowCount()
public int getColumnCount()
public Object getValueAt(int row, int column)
public void setValueAt(Object aValue, int row, int column)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></td>
</tr>
</table>
<p>
<a name="ixa102788"><a href="index_g.html#ixb102062"><font color=#000080><tt>getRowCount</tt></font></a></a>
und <a name="ixa102789"><a href="index_g.html#ixb102063"><font color=#000080><tt>getColumnCount</tt></font></a></a>
liefern die aktuelle Zeilen- bzw. Spaltenzahl der Tabelle. Mit <a name="ixa102790"><a href="index_g.html#ixb102064"><font color=#000080><tt>getValueAt</tt></font></a></a>
kann auf das Element an der Position <i>(row, column)</i> zugegriffen
werden. Beide Indices beginnen bei 0, ein Zugriff außerhalb
der Grenzen wird mit einer <a href="index_a.html#ixb100857"><font color=#000080><tt>ArrayIndexOutOfBoundsException</tt></font></a>
quittiert. Mit <a name="ixa102791"><a href="index_s.html#ixb102065"><font color=#000080><tt>setValueAt</tt></font></a></a>
kann ein Zellenelement sogar verändert werden.
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=1></td>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>
<p>
Bei der Verwendung der Methoden <a href="index_g.html#ixb102064"><font color=#000080><tt>getValueAt</tt></font></a>
und <a href="index_s.html#ixb102065"><font color=#000080><tt>setValueAt</tt></font></a>
ist es wichtig zu wissen, dass die angegebenen Zeilen- und Spaltenwerte
sich auf die aktuelle Ansicht der Tabelle beziehen, nicht auf ihr
Modell. Hat der Anwender beispielsweise die Spalten eins und zwei
vertauscht, würde ein Zugriff auf ein Element in Spalte eins
den Modellwert in Spalte zwei verändern und umgekehrt. Während
dieses Verhalten erwartungskonform ist, wenn der Wert durch den <i>Anwender</i>
editiert wird, würde es bei programmgesteuertem Aufruf zu einem
logischen Fehler kommen, denn das Programm hat natürlich zunächst
einmal keine Kenntnis davon, dass der Anwender die Spaltenreihenfolge
verändert hat. In aller Regel werden programmgesteuerte Zugriffe
auf einzelne Zellen daher nicht mit <a href="index_g.html#ixb102064"><font color=#000080><tt>getValueAt</tt></font></a>
und <a href="index_s.html#ixb102065"><font color=#000080><tt>setValueAt</tt></font></a>
ausgeführt, sondern an die gleichnamigen Methoden des <a href="index_t.html#ixb102032"><font color=#000080><tt>TableModel</tt></font></a>
delegiert.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#CC0000">
<tr>
<td><font color="#FFFFFF"> Warnung </font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
</tr>
</table>
<!-- Section -->
<a name="sectlevel4id038002004002"></a>
<h4>Editieren von Tabellenelementen </h4>
<p>
Nach einem Doppelklick auf eine Zelle kann der Anwender die in diesem
Element enthaltenen Daten verändern. <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
besitzt einige Methoden, mit denen das Programm abfragen kann, ob
und in welcher Zelle die Tabelle gerade editiert wird:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public boolean isEditing()
public int getEditingRow()
public int getEditingColumn()
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></td>
</tr>
</table>
<p>
<a name="ixa102792"><a href="index_i.html#ixb102066"><font color=#000080><tt>isEditing</tt></font></a></a>
gibt genau dann <a href="index_t.html#ixb100233"><font color=#000080><tt>true</tt></font></a>
zurück, wenn gerade ein Element der Tabelle geändert wird.
Mit <a name="ixa102793"><a href="index_g.html#ixb102067"><font color=#000080><tt>getEditingRow</tt></font></a></a>
und <a name="ixa102794"><a href="index_g.html#ixb102068"><font color=#000080><tt>getEditingColumn</tt></font></a></a>
kann das Programm herausfinden, welches Element betroffen ist. Wird
keine Zelle editiert, geben die Methoden -1 zurück. Zudem kann
das Programm durch Aufruf von <a name="ixa102795"><a href="index_e.html#ixb102069"><font color=#000080><tt>editCellAt</tt></font></a></a>
selbst das Editieren eines Tabellenelements einleiten:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public boolean editCellAt(int row, int column)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></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>
Unabhängig von seinem bisherigen Typ wird der geänderte
Wert nach Abschluss des Änderungsvorgangs als <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
in das Modell zurückgeschrieben. Wird - wie im letzten Beispiel
- ein <a href="index_o.html#ixb100224"><font color=#000080><tt>Object</tt></font></a>-Array
als Modell verwendet, ist diese Typkonvertierung zwar korrekt, kann
aber bei der Weiterverarbeitung des Modells zu Überraschungen
führen. Besser ist es, Eingaben des Anwenders direkt nach der
Eingabe zu prüfen und vor der Speicherung in den passenden Typ
umzuwandeln. Wir werden im nächsten Abschnitt zeigen, wie man
das mit Hilfe eines eigenen Tabellenmodells erreichen kann.</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="sectlevel3id038002005"></a>
<h3>38.2.5 Das Tabellenmodell </h3>
<p>
Für einfache Anwendungen reicht es aus, mit den automatisch erzeugten
Tabellenmodellen zu arbeiten. Für Anwendungen mit komplexer strukturierten
Daten, oder solchen, die für ein Array zu umfangreich oder an
externe Quellen gebundenen sind, ist es dagegen sinnvoll, ein eigenes
Tabellenmodell zu implementieren. Dieses muss das Interface <a name="ixa102796"><a href="index_t.html#ixb102032"><font color=#000080><tt>TableModel</tt></font></a></a>
aus dem Paket <a name="ixa102797"><a href="index_j.html#ixb102070"><font color=#000080><tt>javax.swing.table</tt></font></a></a>
implementieren und bei der Instanzierung an den Konstruktor der <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
übergeben. Wahlweise kann auch nach der Instanzierung auf das
Modell zugegriffen werden:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public void setModel(TableModel newModel)
public TableModel getModel()
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></td>
</tr>
</table>
<p>
Das Interface <a href="index_t.html#ixb102032"><font color=#000080><tt>TableModel</tt></font></a>
definiert folgende Methoden:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public int getRowCount()
public int getColumnCount()
public String getColumnName(int columnIndex)
public Class getColumnClass(int columnIndex)
public boolean isCellEditable(int rowIndex, int columnIndex)
public Object getValueAt(int rowIndex, int columnIndex)
public void setValueAt(Object aValue, int rowIndex, int columnIndex)
public void addTableModelListener(TableModelListener l)
public void removeTableModelListener(TableModelListener l)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/table/TableModel.html" onClick="this.href=getApiDoc('javax.swing.table.TableModel')"><font color="#660066" size=-1>javax.swing.table.TableModel</font></a></td>
</tr>
</table>
<p>
Die meisten von ihnen sind Service-Methoden. Sie werden von <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
aufgerufen, um Informationen zur Darstellung der Tabelle zu erhalten.
<a name="ixa102798"><a href="index_g.html#ixb102062"><font color=#000080><tt>getRowCount</tt></font></a></a>
und <a name="ixa102799"><a href="index_g.html#ixb102063"><font color=#000080><tt>getColumnCount</tt></font></a></a>
liefern die Anzahl der Zeilen und Spalten, <a name="ixa102800"><a href="index_g.html#ixb102071"><font color=#000080><tt>getColumnName</tt></font></a></a>
die Spaltenüberschrift und <a name="ixa102801"><a href="index_g.html#ixb102072"><font color=#000080><tt>getColumnClass</tt></font></a></a>
den Typ der Elemente einer Spalte. Mit <a name="ixa102802"><a href="index_i.html#ixb102073"><font color=#000080><tt>isCellEditable</tt></font></a></a>
wird abgefragt, ob eine bestimmte Zelle editiert werden darf oder
nicht. Mit <a name="ixa102803"><a href="index_g.html#ixb102064"><font color=#000080><tt>getValueAt</tt></font></a></a>
fragt die Tabelle beim Modell nach dem Wert einer bestimmten Zelle,
und mit <a name="ixa102804"><a href="index_s.html#ixb102065"><font color=#000080><tt>setValueAt</tt></font></a></a>
wird ein geänderter Wert in das Modell zurückgeschrieben.
<p>
Mit den Methoden <a name="ixa102805"><a href="index_a.html#ixb102074"><font color=#000080><tt>addTableModelListener</tt></font></a></a>
und <a name="ixa102806"><a href="index_r.html#ixb102075"><font color=#000080><tt>removeTableModelListener</tt></font></a></a>
kann ein <a name="ixa102807"><a href="index_t.html#ixb102076"><font color=#000080><tt>TableModelListener</tt></font></a></a>
registriert bzw. deregistriert werden. Er wird über alle Änderungen
des Modells unterrichtet und damit insbesondere aufgerufen, wenn eine
Zeile oder Spalte eingefügt oder gelöscht wurde, wenn der
Inhalt einer Zelle modifiziert wurde oder wenn die Gesamtstruktur
des Modells sich geändert hat. Typischerweise registriert sich
die <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
bei ihrem Modell, um auf Modelländerungen mit entsprechenden
Änderungen der Benutzeroberfläche reagieren zu können.
<!-- Section -->
<a name="sectlevel4id038002005001"></a>
<h4>Beispiel </h4>
<p>
Als Beispiel wollen wir ein Modell konstruieren, das eine sehr große
Tabelle repräsentieren kann (z.B. mit 1000 mal 1000 Elementen),
von denen aber nur sehr wenige tatsächlich einen Wert enthalten
und alle anderen leer sind. Statt einer speicherintensiven Darstellung
mittels eines entsprechend dimensionierten Arrays sollen nur die tatsächlich
belegten Elemente gespeichert werden. Wir wollen dazu eine <a href="index_h.html#ixb100419"><font color=#000080><tt>Hashtable</tt></font></a>
verwenden, deren Elemente die tatsächlich vorhandenen Werte sind.
Als Schlüssel verwenden wir eine String-Darstellung der Koordinaten
des Elements. Der Zugriff auf ein Element erfolgt dann, indem dessen
Koordinatenschlüssel in der <a href="index_h.html#ixb100419"><font color=#000080><tt>Hashtable</tt></font></a>
gesucht und der zugehörige Wert zurückgegeben bzw. gespeichert
wird.
<p>
Um das Tabellenmodell nicht von Grund auf neu entwickeln zu müssen,
leiten wir es aus der Klasse <a name="ixa102808"><a href="index_a.html#ixb102077"><font color=#000080><tt>AbstractTableModel</tt></font></a></a>
des Pakets <a href="index_j.html#ixb102070"><font color=#000080><tt>javax.swing.table</tt></font></a>
ab. Diese bietet für fast alle erforderlichen Methoden Standardimplementierungen
und stellt darüber hinaus einige nützliche Hilfsmethoden
zur Verfügung:
<a name="listingid038006"></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">/* SparseTableModel.java */</font>
<font color="#555555">002 </font>
<font color="#555555">003 </font><font color="#0000AA">import</font> java.util.*;
<font color="#555555">004 </font><font color="#0000AA">import</font> javax.swing.*;
<font color="#555555">005 </font><font color="#0000AA">import</font> javax.swing.table.*;
<font color="#555555">006 </font>
<font color="#555555">007 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> SparseTableModel
<font color="#555555">008 </font><font color="#0000AA">extends</font> AbstractTableModel
<font color="#555555">009 </font>{
<font color="#555555">010 </font> <font color="#0000AA">private</font> <font color="#006699">int</font> size;
<font color="#555555">011 </font> <font color="#0000AA">private</font> Hashtable data;
<font color="#555555">012 </font>
<font color="#555555">013 </font> <font color="#00AA00">//Konstruktor</font>
<font color="#555555">014 </font> <font color="#0000AA">public</font> SparseTableModel(<font color="#006699">int</font> size)
<font color="#555555">015 </font> {
<font color="#555555">016 </font> <font color="#006699">this</font>.size = size;
<font color="#555555">017 </font> <font color="#006699">this</font>.data = <font color="#0000AA">new</font> Hashtable();
<font color="#555555">018 </font> }
<font color="#555555">019 </font>
<font color="#555555">020 </font> <font color="#00AA00">//Methoden für das TableModel-Interface</font>
<font color="#555555">021 </font> <font color="#0000AA">public</font> <font color="#006699">int</font> getRowCount()
<font color="#555555">022 </font> {
<font color="#555555">023 </font> <font color="#0000AA">return</font> size;
<font color="#555555">024 </font> }
<font color="#555555">025 </font>
<font color="#555555">026 </font> <font color="#0000AA">public</font> <font color="#006699">int</font> getColumnCount()
<font color="#555555">027 </font> {
<font color="#555555">028 </font> <font color="#0000AA">return</font> size;
<font color="#555555">029 </font> }
<font color="#555555">030 </font>
<font color="#555555">031 </font> <font color="#0000AA">public</font> String getColumnName(<font color="#006699">int</font> columnIndex)
<font color="#555555">032 </font> {
<font color="#555555">033 </font> <font color="#0000AA">return</font> <font color="#0000FF">"C"</font> + columnIndex;
<font color="#555555">034 </font> }
<font color="#555555">035 </font>
<font color="#555555">036 </font> <font color="#0000AA">public</font> Class getColumnClass(<font color="#006699">int</font> columnIndex)
<font color="#555555">037 </font> {
<font color="#555555">038 </font> <font color="#0000AA">return</font> String.<font color="#0000AA">class</font>;
<font color="#555555">039 </font> }
<font color="#555555">040 </font>
<font color="#555555">041 </font> <font color="#0000AA">public</font> <font color="#006699">boolean</font> isCellEditable(<font color="#006699">int</font> rowIndex, <font color="#006699">int</font> columnIndex)
<font color="#555555">042 </font> {
<font color="#555555">043 </font> <font color="#0000AA">return</font> rowIndex < size && columnIndex < size;
<font color="#555555">044 </font> }
<font color="#555555">045 </font>
<font color="#555555">046 </font> <font color="#0000AA">public</font> Object getValueAt(<font color="#006699">int</font> rowIndex, <font color="#006699">int</font> columnIndex)
<font color="#555555">047 </font> {
<font color="#555555">048 </font> String key = <font color="#0000FF">"["</font> + rowIndex + <font color="#0000FF">","</font> + columnIndex + <font color="#0000FF">"]"</font>;
<font color="#555555">049 </font> String value = (String)data.get(key);
<font color="#555555">050 </font> <font color="#0000AA">return</font> value == <font color="#006699">null</font> ? <font color="#0000FF">"-"</font> : value;
<font color="#555555">051 </font> }
<font color="#555555">052 </font>
<font color="#555555">053 </font> <font color="#0000AA">public</font> <font color="#006699">void</font> setValueAt(Object aValue, <font color="#006699">int</font> rowIndex, <font color="#006699">int</font> columnIndex)
<font color="#555555">054 </font> {
<font color="#555555">055 </font> String key = <font color="#0000FF">"["</font> + rowIndex + <font color="#0000FF">","</font> + columnIndex + <font color="#0000FF">"]"</font>;
<font color="#555555">056 </font> String value = (String)aValue;
<font color="#555555">057 </font> <font color="#0000AA">if</font> (value.length() <= 0) {
<font color="#555555">058 </font> data.remove(key);
<font color="#555555">059 </font> } <font color="#0000AA">else</font> {
<font color="#555555">060 </font> data.put(key, value);
<font color="#555555">061 </font> }
<font color="#555555">062 </font> }
<font color="#555555">063 </font>
<font color="#555555">064 </font> <font color="#00AA00">//Zusätzliche Methoden</font>
<font color="#555555">065 </font> <font color="#0000AA">public</font> <font color="#006699">void</font> printData()
<font color="#555555">066 </font> {
<font color="#555555">067 </font> Enumeration e = data.keys();
<font color="#555555">068 </font> <font color="#0000AA">while</font> (e.hasMoreElements()) {
<font color="#555555">069 </font> String key = (String)e.nextElement();
<font color="#555555">070 </font> System.out.println(
<font color="#555555">071 </font> <font color="#0000FF">"At "</font> + key + <font color="#0000FF">": "</font> + (String)data.get(key)
<font color="#555555">072 </font> );
<font color="#555555">073 </font> }
<font color="#555555">074 </font> }
<font color="#555555">075 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/SparseTableModel.java"><font color="#000055" size=-1>SparseTableModel.java</font></a></td>
</tr>
</table>
<i>
Listing 38.6: Ein Modell für schwach besetzte Tabellen</i></p>
<p>
Die Klasse wird durch Übergabe der Anzahl der Zeilen und Spalten
instanziert. <a href="index_g.html#ixb102062"><font color=#000080><tt>getRowCount</tt></font></a>
und <a href="index_g.html#ixb102063"><font color=#000080><tt>getColumnCount</tt></font></a>
liefern genau diesen Wert zurück. Als Spaltenname wird ein »C«,
gefolgt von der Nummer der Spalte angegeben. Alle Spalten sind vom
Typ <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
und alle Zellen sind editierbar. Wird mit <a href="index_g.html#ixb102064"><font color=#000080><tt>getValueAt</tt></font></a>
der Inhalt einer bestimmten Tabellenzelle abgefragt, so bildet die
Methode den Schlüssel aus Zeilen- und Spaltenindex und sucht
damit in der <a href="index_h.html#ixb100419"><font color=#000080><tt>Hashtable</tt></font></a>
<font color="#000077"><tt>data</tt></font>. Falls ein Eintrag gefunden
wird, gibt <a href="index_g.html#ixb102064"><font color=#000080><tt>getValueAt</tt></font></a>
diesen an den Aufrufer zurück, andernfalls wird nur ein Minuszeichen
geliefert. <a href="index_s.html#ixb102065"><font color=#000080><tt>setValueAt</tt></font></a>
arbeitet analog. Auch hier wird zunächst der Schlüssel gebildet
und dann zusammen mit dem zugehörigen Wert in der <a href="index_h.html#ixb100419"><font color=#000080><tt>Hashtable</tt></font></a>
gespeichert. Die Hilfemethode <font color="#000077"><tt>printData</tt></font>
dient dazu, alle vorhandenen Werte samt Koordinatenschlüsseln
auf der Konsole auszugeben.
<p>
Mit Hilfe dieses Modells Tabellen zu bauen, die auch bei großen
Abmessungen noch effizient arbeiten, ist nicht mehr schwer. Das folgende
Programm zeigt das am Beispiel einer Tabelle mit einer Million Zellen.
Neben der Tabelle enthält es einen Button »Drucken«,
mit dem die aktuelle Belegung der Tabelle ausgegeben werden kann.
<a name="listingid038007"></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">/* Listing3807.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> javax.swing.*;
<font color="#555555">006 </font>
<font color="#555555">007 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing3807
<font color="#555555">008 </font><font color="#0000AA">extends</font> JFrame
<font color="#555555">009 </font><font color="#0000AA">implements</font> ActionListener
<font color="#555555">010 </font>{
<font color="#555555">011 </font> JTable table;
<font color="#555555">012 </font> SparseTableModel tableModel;
<font color="#555555">013 </font>
<font color="#555555">014 </font> <font color="#0000AA">public</font> Listing3807()
<font color="#555555">015 </font> {
<font color="#555555">016 </font> <font color="#006699">super</font>(<font color="#0000FF">"JTable 2"</font>);
<font color="#555555">017 </font> addWindowListener(<font color="#0000AA">new</font> WindowClosingAdapter(<font color="#006699">true</font>));
<font color="#555555">018 </font> tableModel = <font color="#0000AA">new</font> SparseTableModel(1000);
<font color="#555555">019 </font> table = <font color="#0000AA">new</font> JTable(tableModel, <font color="#006699">null</font>);
<font color="#555555">020 </font> table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
<font color="#555555">021 </font> table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
<font color="#555555">022 </font> table.setCellSelectionEnabled(<font color="#006699">true</font>);
<font color="#555555">023 </font> Container cp = getContentPane();
<font color="#555555">024 </font> cp.add(<font color="#0000AA">new</font> JScrollPane(table), BorderLayout.CENTER);
<font color="#555555">025 </font> JButton button = <font color="#0000AA">new</font> JButton(<font color="#0000FF">"Drucken"</font>);
<font color="#555555">026 </font> button.addActionListener(<font color="#006699">this</font>);
<font color="#555555">027 </font> cp.add(button, BorderLayout.SOUTH);
<font color="#555555">028 </font> }
<font color="#555555">029 </font>
<font color="#555555">030 </font> <font color="#0000AA">public</font> <font color="#006699">void</font> actionPerformed(ActionEvent event)
<font color="#555555">031 </font> {
<font color="#555555">032 </font> tableModel.printData();
<font color="#555555">033 </font> }
<font color="#555555">034 </font>
<font color="#555555">035 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
<font color="#555555">036 </font> {
<font color="#555555">037 </font> Listing3807 frame = <font color="#0000AA">new</font> Listing3807();
<font color="#555555">038 </font> frame.setLocation(100, 100);
<font color="#555555">039 </font> frame.setSize(320, 200);
<font color="#555555">040 </font> frame.setVisible(<font color="#006699">true</font>);
<font color="#555555">041 </font> }
<font color="#555555">042 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Listing3807.java"><font color="#000055" size=-1>Listing3807.java</font></a></td>
</tr>
</table>
<i>
Listing 38.7: Eine JTable mit einer Million Zellen</i></p>
<p>
Die Ausgabe des Programms sieht nach einigen Einfügungen so aus:
<p>
<a name="imageid038006"></a>
<img src="images/JTable2.gif">
<p>
<p><i>
Abbildung 38.6: Eine JTable mit einer Million Zellen</i></p>
<p>
Wenn in diesem Zustand der »Drucken«-Button betätigt
wird, gibt das Programm folgende Liste auf der Konsole aus:
<font color="#333300">
<pre>
At [997,998]: große
At [994,997]: Hallo
At [999,999]: Welt
At [996,999]: Tabellen-
</pre>
</font>
<!-- Section -->
<a name="sectlevel3id038002006"></a>
<h3>38.2.6 Das Spaltenmodell </h3>
<p>
Neben dem Tabellenmodell, das die Daten der Tabelle enthält,
besitzt eine <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
ein weiteres Modell, das für die Eigenschaften der Spalten verantwortlich
ist. In unseren bisherigen Beispielen wurde es implizit aus dem Tabellenmodell
und den angegebenen Spaltennamen erzeugt. Sollen neben den Namen weitere
Eigenschaften der Spalten kontrolliert werden, reicht das nicht aus,
und ein eigenes Spaltenmodell muss geschrieben werden.
<p>
Das Spaltenmodell einer <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
muss das Interface <a name="ixa102809"><a href="index_t.html#ixb102033"><font color=#000080><tt>TableColumnModel</tt></font></a></a>
aus dem Paket <a href="index_j.html#ixb102070"><font color=#000080><tt>javax.swing.table</tt></font></a>
implementieren und wird bei der Instanzierung einer <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
an deren Konstruktor übergeben. Da die Implementierung eines
Spaltenmodells recht aufwändig ist, wurde mit der Klasse <a name="ixa102810"><a href="index_d.html#ixb102078"><font color=#000080><tt>DefaultTableColumnModel</tt></font></a></a>
eine Standard-Implementierung geschaffen, die ohne weitere Ableitung
verwendet werden kann. Das zunächst leere Modell stellt Methoden
zur Verfügung, mit denen Spaltenobjekte (sie sind vom Typ <a name="ixa102811"><a href="index_t.html#ixb102079"><font color=#000080><tt>TableColumn</tt></font></a></a>)
hinzugefügt oder entfernt werden können:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public void addColumn(TableColumn aColumn)
public void removeColumn(TableColumn column)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/table/DefaultTableColumnModel.html" onClick="this.href=getApiDoc('javax.swing.table.DefaultTableColumnModel')"><font color="#660066" size=-1>javax.swing.table.DefaultTableColumnModel</font></a></td>
</tr>
</table>
<p>
Jede an das Modell übergebene Instanz der Klasse <a href="index_t.html#ixb102079"><font color=#000080><tt>TableColumn</tt></font></a>
repräsentiert dabei die Eigenschaften einer einzelnen Tabellenspalte.
Mit einer <a href="index_t.html#ixb102079"><font color=#000080><tt>TableColumn</tt></font></a>
können praktisch alle visuellen Eigenschaften der Spalte kontrolliert
werden. So kann die Breite ebenso wie die Spaltenposition festgelegt
werden, und es können beliebige Komponenten zur Darstellung und
zum Editieren der Zellen definiert werden. Wie wollen uns auf ein
einfaches Beispiel beschränken und lediglich zeigen, wie die
anfängliche Breite der Spalten explizit festgelegt werden kann.
<p>
Dazu instanzieren wir ein <a href="index_d.html#ixb102078"><font color=#000080><tt>DefaultTableColumnModel</tt></font></a>
und fügen drei <a href="index_t.html#ixb102079"><font color=#000080><tt>TableColumn</tt></font></a>-Objekte
hinzu. Sie werden jeweils mit folgendem Konstruktor initialisiert:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public TableColumn(int modelIndex, int width)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/table/TableColumn.html" onClick="this.href=getApiDoc('javax.swing.table.TableColumn')"><font color="#660066" size=-1>javax.swing.table.TableColumn</font></a></td>
</tr>
</table>
<p>
Der erste Parameter gibt den Modellindex an, also die Spalte im Tabellenmodell,
zu der die visuelle Spalte korrespondiert. Der zweite Parameter gibt
die initiale Breite der Spalte an. Anschließend rufen wir die
Methode <a name="ixa102812"><a href="index_s.html#ixb102080"><font color=#000080><tt>setHeaderValue</tt></font></a></a>
auf, um die Spaltenbeschriftung zu definieren, und fügen die
Spalte in das Spaltenmodell ein. Das wiederholen wir für alle
drei Spalten und übergeben das Spaltenmodell an den Konstruktor
der Tabelle. Da bei Übergabe eines Spaltenmodells auch das Tabellenmodell
explizit übergeben werden muss, definieren wir es aus unserem
vorhandenen Datenarray durch eine lokale Ableitung der Klasse <a href="index_a.html#ixb102077"><font color=#000080><tt>AbstractTableModel</tt></font></a>:
<a name="listingid038008"></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">/* Listing3808.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> javax.swing.*;
<font color="#555555">005 </font><font color="#0000AA">import</font> javax.swing.table.*;
<font color="#555555">006 </font>
<font color="#555555">007 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing3808
<font color="#555555">008 </font><font color="#0000AA">extends</font> JFrame
<font color="#555555">009 </font><font color="#0000AA">implements</font> TableData
<font color="#555555">010 </font>{
<font color="#555555">011 </font> <font color="#0000AA">public</font> Listing3808()
<font color="#555555">012 </font> {
<font color="#555555">013 </font> <font color="#006699">super</font>(<font color="#0000FF">"JTable 3"</font>);
<font color="#555555">014 </font> addWindowListener(<font color="#0000AA">new</font> WindowClosingAdapter(<font color="#006699">true</font>));
<font color="#555555">015 </font> <font color="#00AA00">//Spaltenmodell erzeugen</font>
<font color="#555555">016 </font> DefaultTableColumnModel cm = <font color="#0000AA">new</font> DefaultTableColumnModel();
<font color="#555555">017 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i < COLHEADS.length; ++i) {
<font color="#555555">018 </font> TableColumn col = <font color="#0000AA">new</font> TableColumn(i, i == 2 ? 150 : 60);
<font color="#555555">019 </font> col.setHeaderValue(COLHEADS[i]);
<font color="#555555">020 </font> cm.addColumn(col);
<font color="#555555">021 </font> }
<font color="#555555">022 </font> <font color="#00AA00">//Tabellenmodell erzeugen</font>
<font color="#555555">023 </font> TableModel tm = <font color="#0000AA">new</font> AbstractTableModel() {
<font color="#555555">024 </font> <font color="#0000AA">public</font> <font color="#006699">int</font> getRowCount()
<font color="#555555">025 </font> {
<font color="#555555">026 </font> <font color="#0000AA">return</font> DATA.length;
<font color="#555555">027 </font> }
<font color="#555555">028 </font> <font color="#0000AA">public</font> <font color="#006699">int</font> getColumnCount()
<font color="#555555">029 </font> {
<font color="#555555">030 </font> <font color="#0000AA">return</font> DATA[0].length;
<font color="#555555">031 </font> }
<font color="#555555">032 </font> <font color="#0000AA">public</font> Object getValueAt(<font color="#006699">int</font> row, <font color="#006699">int</font> column)
<font color="#555555">033 </font> {
<font color="#555555">034 </font> <font color="#0000AA">return</font> DATA[row][column];
<font color="#555555">035 </font> }
<font color="#555555">036 </font> };
<font color="#555555">037 </font> <font color="#00AA00">//Tabelle erzeugen und ContentPane füllen</font>
<font color="#555555">038 </font> JTable table = <font color="#0000AA">new</font> JTable(tm, cm);
<font color="#555555">039 </font> Container cp = getContentPane();
<font color="#555555">040 </font> cp.add(<font color="#0000AA">new</font> JLabel(<font color="#0000FF">"Alte c\'t-Ausgaben:"</font>), BorderLayout.NORTH);
<font color="#555555">041 </font> cp.add(<font color="#0000AA">new</font> JScrollPane(table), BorderLayout.CENTER);
<font color="#555555">042 </font> }
<font color="#555555">043 </font>
<font color="#555555">044 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
<font color="#555555">045 </font> {
<font color="#555555">046 </font> Listing3808 frame = <font color="#0000AA">new</font> Listing3808();
<font color="#555555">047 </font> frame.setLocation(100, 100);
<font color="#555555">048 </font> frame.setSize(350, 200);
<font color="#555555">049 </font> frame.setVisible(<font color="#006699">true</font>);
<font color="#555555">050 </font> }
<font color="#555555">051 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Listing3808.java"><font color="#000055" size=-1>Listing3808.java</font></a></td>
</tr>
</table>
<i>
Listing 38.8: Eine JTable mit einem eigenen Spaltenmodell</i></p>
<p>
Die initialen Spaltenbreiten wurden auf 60 bzw. 150 Zeichen festgelegt,
und die Ausgabe des Programms sieht so aus:
<p>
<a name="imageid038007"></a>
<img src="images/JTable3.gif">
<p>
<p><i>
Abbildung 38.7: Eine JTable mit eigenem Spaltenmodell</i></p>
<!-- Section -->
<a name="sectlevel3id038002007"></a>
<h3>38.2.7 Rendering der Zellen </h3>
<p>
Als Rendering<a name="ixa102813"></a> bezeichnet man den Vorgang,
der dafür sorgt, dass die Zellen auf dem Bildschirm dargestellt
werden. Die dafür verantwortlichen Komponenten werden als <i>Renderer</i>
bezeichnet. Eine <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
besitzt einen Standard-Renderer, auf den mit den Methoden <a name="ixa102814"><a href="index_g.html#ixb102082"><font color=#000080><tt>getDefaultRenderer</tt></font></a></a>
und <a name="ixa102815"><a href="index_s.html#ixb102083"><font color=#000080><tt>setDefaultRenderer</tt></font></a></a>
zugegriffen werden kann:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public TableCellRenderer getDefaultRenderer(Class columnClass)
public void setDefaultRenderer(Class columnClass, TableCellRenderer renderer)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></td>
</tr>
</table>
<p>
Sofern nicht in den Tabellenspalten ein eigener Renderer bestimmt
wird, ist der Standard-Renderer für die Darstellung aller Tabellenelemente
zuständig. Er muss das Interface <a name="ixa102816"><a href="index_t.html#ixb102084"><font color=#000080><tt>TableCellRenderer</tt></font></a></a>
implementieren. Es enthält nur eine einzige Methode:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column
)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/table/TableCellRenderer.html" onClick="this.href=getApiDoc('javax.swing.table.TableCellRenderer')"><font color="#660066" size=-1>javax.swing.table.TableCellRenderer</font></a></td>
</tr>
</table>
<p>
Diese arbeitet als Factory-Methode und wird immer dann aufgerufen,
wenn zur Darstellung einer Zelle ein Renderer benötigt wird.
Mit Hilfe der übergebenen Argumente kann der Renderer bestimmen,
für welche Zelle er aktiv werden soll, welchen Inhalt diese hat,
und ob sie gerade selektiert ist oder den Fokus hat. Zusätzlich
wird die Tabelle selbst übergeben, so dass der Renderer Zugriff
auf deren Eigenschaften und Modelle hat.
<p>
Standardmäßig wird als Renderer eine Instanz der Klasse
<a name="ixa102817"><a href="index_d.html#ixb102085"><font color=#000080><tt>DefaultTableCellRenderer</tt></font></a></a>
verwendet. Sie ist eine Ableitung von <a href="index_j.html#ixb101769"><font color=#000080><tt>JLabel</tt></font></a>,
mit deren Hilfe Farbe, Font und Hintergrund an das Look-and-Feel der
Tabelle und die Erfordernisse der jeweiligen Zelle anpasst werden.
Interessanterweise wird pro Tabelle lediglich eine einzige Instanz
erzeugt und zur Darstellung <i>aller</i> Zellen verwendet. Dazu wird
das Label jeweils an die Position der darzustellenden Tabelle verschoben
und dann mit den erforderlichen visuellen Eigenschaften versehen.
<p>
Da ein <a href="index_j.html#ixb101769"><font color=#000080><tt>JLabel</tt></font></a>
für diese Art von Anwendung eigentlich nicht vorgesehen wurde,
muss <a href="index_d.html#ixb102085"><font color=#000080><tt>DefaultTableCellRenderer</tt></font></a>
aus Performancegründen (insbesondere im JDK 1.3) einige der Standardmechanismen
von Swing-Komponenten deaktivieren oder umdefinieren. Aus diesem Grunde
ist das Ableiten einer eigenen Klasse aus <a href="index_d.html#ixb102085"><font color=#000080><tt>DefaultTableCellRenderer</tt></font></a>
problematisch. Auch das Verwenden des Standard-Renderers in einer
eigenen Renderer-Implementierung (mit dem Ziel, nur die wirklich unterschiedlichen
Eigenschaften zu modifizieren) funktioniert nicht ohne weiteres.
<p>
Das folgende Beispiel zeigt einen Renderer, dessen Aufgabe darin besteht,
die Zellen unserer schon bekannten Tabelle in unterschiedlichen Farben
darzustellen. Die Klasse <a href="index_d.html#ixb102085"><font color=#000080><tt>DefaultTableCellRenderer</tt></font></a>
wird dazu weder per Ableitung noch per Delegation verwendet.
<a name="colorrenderer"></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">/* ColoredTableCellRenderer.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> javax.swing.*;
<font color="#555555">005 </font><font color="#0000AA">import</font> javax.swing.border.*;
<font color="#555555">006 </font><font color="#0000AA">import</font> javax.swing.table.*;
<font color="#555555">007 </font>
<font color="#555555">008 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> ColoredTableCellRenderer
<font color="#555555">009 </font><font color="#0000AA">implements</font> TableCellRenderer
<font color="#555555">010 </font>{
<font color="#555555">011 </font> <font color="#0000AA">private</font> Color lightBlue = <font color="#0000AA">new</font> Color(160, 160, 255);
<font color="#555555">012 </font> <font color="#0000AA">private</font> Color darkBlue = <font color="#0000AA">new</font> Color( 64, 64, 128);
<font color="#555555">013 </font>
<font color="#555555">014 </font> <font color="#0000AA">public</font> Component getTableCellRendererComponent(
<font color="#555555">015 </font> JTable table,
<font color="#555555">016 </font> Object value,
<font color="#555555">017 </font> <font color="#006699">boolean</font> isSelected,
<font color="#555555">018 </font> <font color="#006699">boolean</font> hasFocus,
<font color="#555555">019 </font> <font color="#006699">int</font> row,
<font color="#555555">020 </font> <font color="#006699">int</font> column
<font color="#555555">021 </font> )
<font color="#555555">022 </font> {
<font color="#555555">023 </font> <font color="#00AA00">//Label erzeugen</font>
<font color="#555555">024 </font> JLabel label = <font color="#0000AA">new</font> JLabel((String)value);
<font color="#555555">025 </font> label.setOpaque(<font color="#006699">true</font>);
<font color="#555555">026 </font> Border b = BorderFactory.createEmptyBorder(1, 1, 1, 1);
<font color="#555555">027 </font> label.setBorder(b);
<font color="#555555">028 </font> label.setFont(table.getFont());
<font color="#555555">029 </font> label.setForeground(table.getForeground());
<font color="#555555">030 </font> label.setBackground(table.getBackground());
<font color="#555555">031 </font> <font color="#0000AA">if</font> (hasFocus) { <a name="colorrenderer.a"></a>
<font color="#555555">032 </font> label.setBackground(darkBlue);
<font color="#555555">033 </font> label.setForeground(Color.white);
<font color="#555555">034 </font> } <font color="#0000AA">else</font> <font color="#0000AA">if</font> (isSelected) {
<font color="#555555">035 </font> label.setBackground(lightBlue);
<font color="#555555">036 </font> } <font color="#0000AA">else</font> {
<font color="#555555">037 </font> <font color="#00AA00">//Angezeigte Spalte in Modellspalte umwandeln</font>
<font color="#555555">038 </font> column = table.convertColumnIndexToModel(column); <a name="colorrenderer.b"></a>
<font color="#555555">039 </font> <font color="#0000AA">if</font> (column == 1) {
<font color="#555555">040 </font> <font color="#006699">int</font> numpages = Integer.parseInt((String)value);
<font color="#555555">041 </font> <font color="#0000AA">if</font> (numpages >= 250) {
<font color="#555555">042 </font> label.setBackground(Color.red);
<font color="#555555">043 </font> } <font color="#0000AA">else</font> <font color="#0000AA">if</font> (numpages >= 200) {
<font color="#555555">044 </font> label.setBackground(Color.orange);
<font color="#555555">045 </font> } <font color="#0000AA">else</font> {
<font color="#555555">046 </font> label.setBackground(Color.yellow);
<font color="#555555">047 </font> }
<font color="#555555">048 </font> }
<font color="#555555">049 </font> }
<font color="#555555">050 </font> <font color="#0000AA">return</font> label;
<font color="#555555">051 </font> }
<font color="#555555">052 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/ColoredTableCellRenderer.java"><font color="#000055" size=-1>ColoredTableCellRenderer.java</font></a></td>
</tr>
</table>
<i>
Listing 38.9: Ein eigener Zellrenderer</i></p>
<p>
<a name="ixa102818"><a href="index_g.html#ixb102086"><font color=#000080><tt>getTableCellRendererComponent</tt></font></a></a>
erzeugt bei jedem Aufruf ein neues <a href="index_j.html#ixb101769"><font color=#000080><tt>JLabel</tt></font></a>,
dessen Beschriftung dem Zelleninhalt entspricht. Es bekommt einen
nicht-transparenten Hintergrund und einen unsichtbaren Rahmen von
einem Pixel Breite (damit die Zellen nicht direkt aneinanderstoßen).
Anschließend werden Schriftart, Vorder- und Hintergrundfarbe
von der Tabelle übernommen.
<p>
Ab <a href="k100245.html#colorrenderer.a">Zeile 031</a> beginnt die
Definition der Vorder- und Hintergrundfarbe. Hat das Element den Fokus,
wird es in dunkelblau auf weiß gezeichnet. Ist es lediglich
selektiert, wird der Hintergrund hellblau eingefärbt. Ist beides
nicht der Fall, prüft die Methode, ob das darzustellende Element
aus der Spalte mit den Seitenzahlen stammt. Dazu ist es zunächst
nötig, in <a href="k100245.html#colorrenderer.b">Zeile 038</a>
den visuellen Spaltenwert in die korrespondierende Modellspalte umzurechnen
(vertauscht der Anwender Spalten, unterscheiden sich beide Werte).
Abhängig von der vorgefundenen Seitenzahl wird der Hintergrund
dann gelb, orange oder rot dargestellt.
<p>
Dieser Renderer kann sehr leicht durch Aufruf von <a href="index_s.html#ixb102083"><font color=#000080><tt>setDefaultRenderer</tt></font></a>
in die Tabelle integriert werden:
<a name="listingid038010"></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">/* Listing3810.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> javax.swing.*;
<font color="#555555">005 </font>
<font color="#555555">006 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing3810
<font color="#555555">007 </font><font color="#0000AA">extends</font> JFrame
<font color="#555555">008 </font><font color="#0000AA">implements</font> TableData
<font color="#555555">009 </font>{
<font color="#555555">010 </font> <font color="#0000AA">public</font> Listing3810()
<font color="#555555">011 </font> {
<font color="#555555">012 </font> <font color="#006699">super</font>(<font color="#0000FF">"JTable 4"</font>);
<font color="#555555">013 </font> addWindowListener(<font color="#0000AA">new</font> WindowClosingAdapter(<font color="#006699">true</font>));
<font color="#555555">014 </font> JTable table = <font color="#0000AA">new</font> JTable(DATA, COLHEADS);
<font color="#555555">015 </font> table.setDefaultRenderer(
<font color="#555555">016 </font> Object.<font color="#0000AA">class</font>,
<font color="#555555">017 </font> <font color="#0000AA">new</font> ColoredTableCellRenderer()
<font color="#555555">018 </font> );
<font color="#555555">019 </font> Container cp = getContentPane();
<font color="#555555">020 </font> cp.add(<font color="#0000AA">new</font> JLabel(<font color="#0000FF">"Alte c\'t-Ausgaben:"</font>), BorderLayout.NORTH);
<font color="#555555">021 </font> cp.add(<font color="#0000AA">new</font> JScrollPane(table), BorderLayout.CENTER);
<font color="#555555">022 </font> }
<font color="#555555">023 </font>
<font color="#555555">024 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
<font color="#555555">025 </font> {
<font color="#555555">026 </font> Listing3810 frame = <font color="#0000AA">new</font> Listing3810();
<font color="#555555">027 </font> frame.setLocation(100, 100);
<font color="#555555">028 </font> frame.setSize(350, 200);
<font color="#555555">029 </font> frame.setVisible(<font color="#006699">true</font>);
<font color="#555555">030 </font> }
<font color="#555555">031 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Listing3810.java"><font color="#000055" size=-1>Listing3810.java</font></a></td>
</tr>
</table>
<i>
Listing 38.10: Eine Tabelle mit einem eigenen Zellrenderer</i></p>
<p>
Die Ausgabe des Programms sieht nun so aus:
<p>
<a name="imageid038008"></a>
<img src="images/JTable4.gif">
<p>
<p><i>
Abbildung 38.8: Eine Tabelle mit einem eigenen Zellrenderer</i></p>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=1></td>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>
<p>
Der Renderer erzeugt bei jedem Aufruf von <a href="index_g.html#ixb102086"><font color=#000080><tt>getTableCellRendererComponent</tt></font></a>
eine neue Instanz der Klasse <a href="index_j.html#ixb101769"><font color=#000080><tt>JLabel</tt></font></a>.
Da das während der Arbeit mit der Tabelle sehr häufig erfolgt
(schon das Bewegen des Mauszeigers über der Tabelle löst
etliche Aufrufe aus), ist diese Vorgehensweise recht ineffizient und
belastet den Garbage Collector. In »echten« Programmen sollte
daher mehr Aufwand getrieben werden. So könnten beispielsweise
Renderer in einem Cache zwischengespeichert und bei erneutem Bedarf
wiederverwendet werden. Oder das Programm könnte eine Technik
ähnlich der von <a href="index_d.html#ixb102085"><font color=#000080><tt>DefaultTableCellRenderer</tt></font></a>
verwenden und nur eine einzige Instanz erzeugen. Die Lektüre
des Quelltextes der Klasse zeigt, wie es gemacht wird.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#CC0000">
<tr>
<td><font color="#FFFFFF"> Warnung </font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
</tr>
</table>
<!-- Section -->
<a name="sectlevel3id038002008"></a>
<h3>38.2.8 Reaktion auf Ereignisse </h3>
<p>
Eine <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
generiert eine Vielzahl von Ereignissen, um registrierte Listener
über Änderungen des Tabellenzustands zu informieren. Will
ein Objekt beispielsweise darüber informiert werden, dass sich
die Selektion geändert hat, muss es zwei <a href="index_l.html#ixb101966"><font color=#000080><tt>ListSelectionListener</tt></font></a>
registrieren. Einer davon wird auf dem Selektionsmodell registriert,
das mit <a name="ixa102819"><a href="index_g.html#ixb102087"><font color=#000080><tt>getSelectionModel</tt></font></a></a>
ermittelt werden kann. Da dieser nur Informationen über Änderungen
an der Zeilenselektion versendet, muss ein zweiter Listener auf dem
Modell für die Spaltenselektion registriert werden. Es kann durch
Aufruf von <a name="ixa102820"><a href="index_g.html#ixb102088"><font color=#000080><tt>getColumnModel</tt></font></a></a>
beschafft werden, und auf sein Selektionsmodell kann ebenfalls mit
<a name="ixa102819"><a href="index_g.html#ixb102087"><font color=#000080><tt>getSelectionModel</tt></font></a></a>
zugegriffen werden. Bei jeder Änderung der Selektion wird nun
<a href="index_v.html#ixb101969"><font color=#000080><tt>valueChanged</tt></font></a>
aufgerufen und kann mit Hilfe der oben erläuterten Methoden herausfinden,
welche Zeilen und Spalten selektiert sind.
<p>
Die Tabelle informiert auch über Änderungen ihrer Daten.
Dazu muss auf dem Tabellenmodell (das mit <a href="index_g.html#ixb101972"><font color=#000080><tt>getModel</tt></font></a>
beschafft wird) durch Aufruf von <a href="index_a.html#ixb102074"><font color=#000080><tt>addTableModelListener</tt></font></a>
ein <a href="index_t.html#ixb102076"><font color=#000080><tt>TableModelListener</tt></font></a>
registriert werden. Bei jeder Änderung des Modells wird dann
dessen Methode <a name="ixa102821"><a href="index_t.html#ixb102089"><font color=#000080><tt>tableChanged</tt></font></a></a>
aufgerufen.
<p>
Schließlich können auch alle in den Vaterklassen von <a href="index_j.html#ixb102031"><font color=#000080><tt>JTable</tt></font></a>
definierten Listener registriert werden. Soll beispielsweise auf einen
Klick mit der rechten Maustaste reagiert werden, kann durch Aufruf
von <a href="index_a.html#ixb101422"><font color=#000080><tt>addMouseListener</tt></font></a>
ein <a href="index_m.html#ixb101416"><font color=#000080><tt>MouseListener</tt></font></a>
registriert werden. Innerhalb seiner Ereignismethoden kann mit <a href="index_g.html#ixb101511"><font color=#000080><tt>getX</tt></font></a>
und <a href="index_g.html#ixb101512"><font color=#000080><tt>getY</tt></font></a>
die aktuelle Mausposition abgefragt und mit den Methoden <a name="ixa102822"><a href="index_r.html#ixb102090"><font color=#000080><tt>rowAtPoint</tt></font></a></a>
und <a name="ixa102823"><a href="index_c.html#ixb102091"><font color=#000080><tt>columnAtPoint</tt></font></a></a>
in Zeilen- und Spaltenwerte der Tabelle umgerechnet werden:
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
public int rowAtPoint(Point point)
public int columnAtPoint(Point point)
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/javax/swing/JTable.html" onClick="this.href=getApiDoc('javax.swing.JTable')"><font color="#660066" size=-1>javax.swing.JTable</font></a></td>
</tr>
</table>
<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="k100243.html"> << </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100244.html"> < </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100246.html"> > </a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100248.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>
|