1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.cosylab.gui.components;
21
22 import java.awt.Color;
23 import java.awt.Font;
24 import java.awt.Graphics;
25 import java.awt.Graphics2D;
26 import java.awt.Point;
27 import java.awt.Rectangle;
28 import java.awt.event.ActionEvent;
29 import java.awt.event.ComponentAdapter;
30 import java.awt.event.ComponentEvent;
31 import java.awt.event.WindowAdapter;
32 import java.awt.event.WindowEvent;
33 import java.awt.image.BufferedImage;
34
35 import javax.swing.AbstractAction;
36 import javax.swing.JPanel;
37
38 import com.cosylab.application.state.State;
39 import com.cosylab.application.state.StateFactory;
40 import com.cosylab.application.state.StateOriginator;
41 import com.cosylab.gui.components.customizer.AbstractCustomizerPanel;
42 import com.cosylab.gui.components.gauger.Needle;
43 import com.cosylab.gui.components.gauger.ScaleTransform;
44 import com.cosylab.gui.components.gauger.ScaleTransformFactory;
45 import com.cosylab.gui.components.gauger.ScaleTransformRenderer;
46 import com.cosylab.gui.components.gauger.ValueLabel;
47 import com.cosylab.gui.components.range2.LinearRange;
48 import com.cosylab.gui.components.range2.LogarithmicRange;
49 import com.cosylab.gui.components.range2.ManualTickCalculator;
50 import com.cosylab.gui.components.range2.RangedValueController;
51 import com.cosylab.gui.components.range2.RangedValueEvent;
52 import com.cosylab.gui.components.range2.RangedValueListener;
53 import com.cosylab.gui.components.range2.RangedValuePolicy;
54 import com.cosylab.gui.components.range2.RescalingValuePolicy;
55 import com.cosylab.gui.components.range2.ShiftValuePolicy;
56 import com.cosylab.gui.components.range2.Tick;
57 import com.cosylab.gui.components.range2.TickParameters;
58 import com.cosylab.gui.components.range2.TrimValuePolicy;
59 import com.cosylab.gui.components.util.ColorHelper;
60 import com.cosylab.gui.components.util.PaintHelper;
61 import com.cosylab.gui.components.util.PopupManageable;
62 import com.cosylab.gui.components.util.PopupManager;
63 import com.cosylab.gui.components.util.ScreenCapturer;
64 import com.cosylab.util.PrintfFormat;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 public class Gauger extends JPanel implements TickParameters, PopupManageable,
89 StateOriginator
90 {
91 private static final long serialVersionUID = 1L;
92
93
94
95
96
97
98
99 public static final int FIXED_SCALE = 0;
100
101
102
103
104
105
106
107 public static final int CONSTANT_SPAN = 1;
108
109
110
111
112
113
114
115 public static final int STRETCH_SCALE = 2;
116
117 private AbstractCustomizerPanel customizer;
118
119 private PopupManager popupManager;
120
121
122
123
124 private Color scaleColor = new Color(239, 239, 239);
125 private Color needleColor = new Color(0, 192, 0);
126 private Color alarmColor = new Color(239,0,0);
127 private Color warningColor = new Color(0xEEEC300);
128 private Color outOfBoundsColor = new Color(239,0,0);
129
130 private Font tickTextFont = new Font("Serif", Font.PLAIN, 12);
131 private Font valueLabelFont = new Font("dialog", Font.PLAIN, 12);
132
133
134
135 private double lowAlarmLimit = 0.05;
136 private double lowWarningLimit= 0.2;
137 private double highWarningLimit= 0.8;
138 private double highAlarmLimit= 0.95;
139 private PrintfFormat formatter = new PrintfFormat("%3.2f");
140 protected RangedValueController userRangedValue;
141 private BufferedImage buffer = null;
142 private ScaleTransformRenderer scaleRenderer = null;
143 private ScaleTransform transform = null;
144 protected Needle needle = null;
145 private ValueLabel valueLabel = null;
146 private double labelValue;
147 private Tick[] ticks = null;
148 private String title = "";
149 private boolean titleVisible = false;
150 private int titleMinimumFontSize = 2;
151 private int titleMaximumFontSize = 20;
152 private boolean resizable = true;
153 private boolean popupEnabled;
154
155 private class ComponentListener extends ComponentAdapter
156 {
157
158
159
160
161
162
163
164
165 public void componentResized(ComponentEvent e)
166 {
167 if (e.getSource() == Gauger.this) {
168 synchronized (Gauger.this) {
169 transform = null;
170 clearBuffer();
171 repaint();
172 }
173 }
174 }
175
176
177
178
179
180
181
182
183
184 public void componentHidden(ComponentEvent e)
185 {
186 super.componentHidden(e);
187 clearBuffer();
188 }
189 }
190
191 private class ValueListener implements RangedValueListener
192 {
193
194
195
196
197
198
199 public void valueChanged(RangedValueEvent event)
200 {
201
202 synchronized (Gauger.this) {
203 if (event.isMinimumChanged() || event.isMaximumChanged()) {
204 clearBuffer();
205 repaint();
206 }
207
208
209 Needle needle = getNeedle();
210 Rectangle oldArea = needle.getBounds();
211
212
213
214 if(getValue()>getMaximum()) {
215 needle.setPosition(userRangedValue.getRelativeValue()+0.05);
216 } else if (getValue()<getMinimum()){
217 needle.setPosition(userRangedValue.getRelativeValue()-0.05);
218 } else {
219 needle.setPosition(userRangedValue.getRelativeValue());
220 }
221
222 if (needle.isChangeSignificant()) {
223 repaint(oldArea);
224 repaint(needle.getBounds());
225 }
226
227 ValueLabel vl = getValueLabel();
228 oldArea = vl.getBounds();
229
230 if (vl.isChangeSignificant()) {
231 repaint(oldArea);
232 repaint(vl.getBounds());
233 }
234 }
235 }
236 }
237
238
239
240
241 public Gauger()
242 {
243 super();
244
245 userRangedValue = new RangedValueController();
246 userRangedValue.setRange(new LinearRange());
247 userRangedValue.addPolicy(new RescalingValuePolicy());
248 userRangedValue.addRangedValueListener(new ValueListener());
249
250
251 setScaleMode(Gauger.FIXED_SCALE);
252 setBackground(ColorHelper.getCosyControl());
253 scaleRenderer = new ScaleTransformRenderer(this);
254
255 setDoubleBuffered(false);
256 setOpaque(true);
257 setDropTarget(null);
258
259 addComponentListener(new ComponentListener());
260 setPopupEnabled(true);
261 }
262
263
264
265
266
267
268
269
270 private synchronized BufferedImage getBuffer()
271 {
272 if (buffer == null) {
273 int w = Math.max(getWidth(), 1);
274 int h = Math.max(getHeight(), 1);
275
276 buffer = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR);
277
278 Graphics2D g2 = buffer.createGraphics();
279 g2.setRenderingHints(PaintHelper.getAntialiasingHints());
280
281 g2.setColor(getBackground());
282 g2.fillRect(0, 0, w, h);
283 scaleRenderer.render(getTransform(), g2);
284 }
285
286 return buffer;
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 public void setScaleMode(int mode)
327 {
328 int oldValue = getScaleMode();
329 switch (mode) {
330 case FIXED_SCALE:
331 setValuePolicy(new TrimValuePolicy());
332 break;
333
334 case CONSTANT_SPAN:
335 setValuePolicy(new ShiftValuePolicy());
336
337 break;
338
339 case STRETCH_SCALE:default:
340 setValuePolicy(new RescalingValuePolicy());
341
342 break;
343 }
344
345 firePropertyChange("scaleMode", oldValue, mode);
346 }
347
348
349
350
351
352
353
354 public void setValuePolicy(RangedValuePolicy policy) {
355 RangedValuePolicy oldValue = getValuePolicy();
356 getRangedValue().setPolicy(policy);
357 firePropertyChange("valuePolicy", oldValue, policy);
358 }
359
360
361
362
363
364
365
366 public RangedValuePolicy getValuePolicy() {
367 return getRangedValue().getPolicy();
368 }
369
370
371
372
373
374
375
376
377
378
379
380 public int getScaleMode()
381 {
382 RangedValuePolicy p = getValuePolicy();
383
384 if (p instanceof TrimValuePolicy) {
385 return FIXED_SCALE;
386 }
387
388 if (p instanceof ShiftValuePolicy) {
389 return CONSTANT_SPAN;
390 }
391
392 return STRETCH_SCALE;
393 }
394
395
396
397
398 private synchronized void clearBuffer()
399 {
400 ticks = null;
401 buffer = null;
402 transform = null;
403 }
404
405
406
407
408
409
410 public double getMaximum()
411 {
412 return userRangedValue.getMaximum();
413 }
414
415
416
417
418
419
420 public double getMinimum()
421 {
422 return userRangedValue.getMinimum();
423 }
424
425
426
427
428
429
430
431
432 protected synchronized Needle getNeedle()
433 {
434 if (needle == null) {
435 needle = new Needle(this);
436 needle.setPosition(0.5);
437 }
438
439 return needle;
440 }
441
442
443
444
445
446
447
448
449 public RangedValueController getRangedValue()
450 {
451 return userRangedValue;
452 }
453
454
455
456
457
458
459
460 public double getValue()
461 {
462 return labelValue;
463 }
464
465
466
467
468
469
470 protected ValueLabel getValueLabel()
471 {
472 if (valueLabel == null) {
473 valueLabel = new ValueLabel(this);
474 }
475
476 return valueLabel;
477 }
478
479
480
481
482
483
484 public void setFormat(String format)
485 {
486 String old = getValueLabel().getFormat();
487
488 try {
489 getValueLabel().setFormat(format);
490 } catch (Exception e) {
491 e.printStackTrace();
492 }
493 formatter = new PrintfFormat(format);
494 repaint();
495
496 firePropertyChange("format", old, format);
497 }
498
499
500
501
502
503
504 public String getFormat()
505 {
506 return getValueLabel().getFormat();
507 }
508
509
510
511
512
513
514 public void setUnits(String units)
515 {
516 String oldValue = getUnits();
517 getValueLabel().setUnits(units);
518 repaint();
519 firePropertyChange("units", oldValue, units);
520 }
521
522
523
524
525
526
527 public String getUnits()
528 {
529 return getValueLabel().getUnits();
530 }
531
532
533
534
535
536
537 public void setUnitsVisible(boolean b)
538 {
539 if (this.isUnitsVisible() == b) return;
540 getValueLabel().setUnitsVisible(b);
541 repaint();
542 firePropertyChange("unitsVisible", !b, b);
543 }
544
545
546
547
548
549
550 public boolean isUnitsVisible()
551 {
552 return getValueLabel().isUnitsVisible();
553 }
554
555
556
557
558
559
560
561
562
563 public void setValue(double newValue)
564 {
565 double old = labelValue;
566 labelValue = newValue;
567 getValueLabel().setValue(labelValue);
568
569 try {
570 userRangedValue.setValue(newValue);
571 } catch (Exception e) {
572 e.printStackTrace();
573 }
574
575 repaint();
576
577 firePropertyChange("value", new Double(old), new Double(newValue));
578 }
579
580
581
582
583
584
585
586 public Tick[] getTicks()
587 {
588 if (ticks == null) {
589
590 ticks = userRangedValue.calculateTicks((int)getTransform().scaleWidth(0.7), this);
591 }
592 return ticks;
593 }
594
595
596
597
598
599
600
601
602 public ScaleTransform getTransform()
603 {
604 if (transform == null) {
605 transform = ScaleTransformFactory.createTransform(getWidth(),
606 getHeight());
607
608 transform.setParameters(getWidth(), getHeight(), 0,
609 getValueLabel().getBounds().height, Tick.TICKS_OFFSET_PIXELS);
610
611 getNeedle().setTransform(transform);
612 setValueLabelPosition(getTransform().getLabelPosition());
613 }
614
615 return transform;
616 }
617
618
619
620
621
622
623
624 public void setMinimum(double newMin)
625 {
626 double oldValue = getMinimum();
627 userRangedValue.setValue(newMin, getMaximum(), getValue());
628 repaint();
629 firePropertyChange("minimum", oldValue, newMin);
630 }
631
632
633
634
635
636
637
638 public void setMaximum(double newMax)
639 {
640 double oldValue = getMaximum();
641 userRangedValue.setValue(getMinimum(), newMax, getValue());
642 repaint();
643 firePropertyChange("maximum", oldValue, newMax);
644 }
645
646
647
648
649
650
651
652
653 public void setValue(double newMin, double newMax, double newVal)
654 {
655 double old = labelValue;
656 labelValue = newVal;
657 getValueLabel().setValue(newVal);
658 userRangedValue.setValue(newMin, newMax, newVal);
659 firePropertyChange("value", new Double(old), new Double(newVal));
660 }
661
662
663
664
665
666
667 public void setValueLabelPosition(Point p)
668 {
669 getValueLabel().setPosition(p.x, p.y);
670 }
671
672
673
674
675
676
677
678
679 protected void paintComponent(Graphics g)
680 {
681 clearBuffer();
682
683
684 try {
685
686 Graphics2D g2 = (Graphics2D)g;
687
688
689
690 g.drawImage(getBuffer(), 0, 0, null);
691 g2.addRenderingHints(PaintHelper.getAntialiasingHints());
692 getNeedle().setTransform(getTransform());
693 getNeedle().render(g2);
694 g2.setColor(getForeground());
695 getValueLabel().draw(g2);
696
697
698 } catch (Exception e) {
699
700
701 }
702 }
703
704
705
706
707 public void setLogarithmicScale()
708 {
709 userRangedValue.setRange(new LogarithmicRange());
710 repaint();
711 }
712
713
714
715
716 public void setLinearScale()
717 {
718 userRangedValue.setRange(new LinearRange());
719 repaint();
720 }
721
722
723
724
725
726
727 public boolean isLogarithmicScale()
728 {
729 return userRangedValue.getRange() instanceof LogarithmicRange;
730 }
731
732
733
734
735
736
737 public boolean isLinearScale()
738 {
739 return userRangedValue.getRange() instanceof LinearRange;
740 }
741
742
743
744
745
746
747
748
749 public int measureTick(double position, String text)
750 {
751 return getTransform().measureTick(getBuffer().getGraphics(), position,
752 text);
753
754
755
756
757 }
758
759
760
761
762
763
764 public PopupManager getPopupManager()
765 {
766 if (popupManager == null) {
767 popupManager = new PopupManager(this, false);
768 popupManager.addAction(new AbstractAction("Preferences...") {
769 private static final long serialVersionUID = 1L;
770 public void actionPerformed(ActionEvent e)
771 {
772 getCustomizer().showDialog();
773 }
774 });
775 popupManager.addAction(new AbstractAction("Capture screen...") {
776 private static final long serialVersionUID = 1L;
777 public void actionPerformed(ActionEvent e)
778 {
779 ScreenCapturer sc = new ScreenCapturer(Gauger.this);
780 sc.showScreenDialog();
781
782 }
783 });
784 }
785
786 return popupManager;
787 }
788
789
790
791
792
793
794 public boolean isPopupEnabled() {
795 return popupEnabled;
796 }
797
798
799
800
801
802
803 public void setPopupEnabled(boolean enabled) {
804 if (popupEnabled == enabled) return;
805 popupEnabled = enabled;
806 if (enabled) {
807 addMouseListener(getPopupManager().getMouseHook());
808 } else {
809 removeMouseListener(getPopupManager().getMouseHook());
810 }
811 firePropertyChange("popupEnabled",!popupEnabled,popupEnabled);
812 }
813
814
815
816
817
818
819 public AbstractCustomizerPanel getCustomizer()
820 {
821 if (customizer == null) {
822 customizer = AbstractCustomizerPanel.findCustomizer(this);
823 }
824 return customizer;
825 }
826
827
828
829
830 public State getState()
831 {
832 State s = StateFactory.createState();
833 s.putDouble("Min", getMinimum());
834 s.putDouble("Max", getMaximum());
835 s.putString("Format", getFormat());
836 s.putString("Units", getUnits());
837 s.putBoolean("LogarithmicScale", isLogarithmicScale());
838 s.putBoolean("LinearScale", isLinearScale());
839 s.putInt("ScaleMode", getScaleMode());
840 s.putFont("Font", getValueLabelFont());
841
842 return s;
843 }
844
845
846
847
848 public void setState(State state)
849 {
850 setMinimum(state.getDouble("Min", getMinimum()));
851 setMaximum(state.getDouble("Max", getMaximum()));
852 setFormat(state.getString("Format", getFormat()));
853 setUnits(state.getString("Units", getUnits()));
854
855 if (state.getBoolean("LogarithmicScale", false)) {
856 setLogarithmicScale();
857 }
858
859 if (state.getBoolean("LinearScale", false)) {
860 setLinearScale();
861 }
862
863 setScaleMode(state.getInt("ScaleMode", getScaleMode()));
864 setValueLabelFont(state.getFont("Font"));
865 }
866
867
868
869
870
871
872 public void setTickTextFont(Font tickText)
873 {
874 Font oldValue = getTickTextFont();
875 this.tickTextFont = tickText;
876 firePropertyChange("tickTextFont", oldValue, tickText);
877 }
878
879
880
881
882
883
884 public Font getTickTextFont()
885 {
886 return tickTextFont;
887 }
888
889
890
891
892
893
894 public Color getScaleColor()
895 {
896 return scaleColor;
897 }
898
899
900
901
902
903
904 public void setScaleColor(Color newScaleColor)
905 {
906 Color oldValue = getScaleColor();
907 scaleColor = newScaleColor;
908 firePropertyChange("scaleColor", oldValue, newScaleColor);
909 }
910
911
912
913
914
915
916 public Color getNeedleColor()
917 {
918 return needleColor;
919 }
920
921
922
923
924
925
926
927 public void setNeedleColor(Color newNeedleColor)
928 {
929 Color oldValue = getNeedleColor();
930 needleColor = newNeedleColor;
931 firePropertyChange("needleColor", oldValue, newNeedleColor);
932 }
933
934
935
936
937
938
939 public Font getValueLabelFont()
940 {
941 return valueLabelFont;
942 }
943
944
945
946
947
948
949 public void setValueLabelFont(Font value)
950 {
951 Font oldValue = getValueLabelFont();
952 valueLabelFont = value;
953 firePropertyChange("valueLabelFont", oldValue, value);
954 }
955
956
957
958
959
960
961
962 public void setLowWarningLimit(double v){
963 double oldValue = getLowWarningLimit();
964 lowWarningLimit = v;
965 firePropertyChange("lowWarningLimit", oldValue, v);
966 }
967
968
969
970
971
972
973 public double getLowWarningLimit(){
974 return lowWarningLimit;
975 }
976
977
978
979
980
981
982
983 public void setLowAlarmLimit(double v){
984 double oldValue = getLowAlarmLimit();
985 lowAlarmLimit = v;
986 firePropertyChange("lowAlarmLimit", oldValue, v);
987 }
988
989
990
991
992
993
994 public double getLowAlarmLimit(){
995 return lowAlarmLimit;
996 }
997
998
999
1000
1001
1002
1003
1004 public void setHighWarningLimit(double v){
1005 double oldValue = getHighWarningLimit();
1006 highWarningLimit = v;
1007 firePropertyChange("highWarningLimit", oldValue, v);
1008 }
1009
1010
1011
1012
1013
1014
1015 public double getHighWarningLimit(){
1016 return highWarningLimit;
1017 }
1018
1019
1020
1021
1022
1023
1024
1025 public void setHighAlarmLimit(double v){
1026 double oldValue = getHighAlarmLimit();
1027 highAlarmLimit = v;
1028 firePropertyChange("highAlarmLimit", oldValue, v);
1029 }
1030
1031
1032
1033
1034
1035
1036 public double getHighAlarmLimit(){
1037 return highAlarmLimit;
1038 }
1039
1040
1041
1042
1043
1044
1045 public Color getAlarmColor() {
1046 return alarmColor;
1047 }
1048
1049
1050
1051
1052
1053
1054 public void setAlarmColor(Color alarmColor) {
1055 Color oldValue = getAlarmColor();
1056 this.alarmColor = alarmColor;
1057 firePropertyChange("alarmColor", oldValue, alarmColor);
1058 }
1059
1060
1061
1062
1063
1064
1065 public Color getOutOfBoundsColor() {
1066 return outOfBoundsColor;
1067 }
1068
1069
1070
1071
1072
1073
1074 public void setOutOfBoundsColor(Color outOfBoundsColor) {
1075 Color oldValue = getOutOfBoundsColor();
1076 this.outOfBoundsColor = outOfBoundsColor;
1077 firePropertyChange("outOfBoundsColor", oldValue, outOfBoundsColor);
1078 }
1079
1080
1081
1082
1083
1084
1085 public Color getWarningColor() {
1086 return warningColor;
1087 }
1088
1089
1090
1091
1092
1093
1094 public void setWarningColor(Color warningColor) {
1095 Color oldValue = getWarningColor();
1096 this.warningColor = warningColor;
1097 firePropertyChange("warningColor", oldValue, warningColor);
1098 }
1099
1100
1101
1102
1103
1104
1105
1106 protected String getTitle() {
1107 return title;
1108 }
1109
1110
1111
1112
1113
1114
1115 protected void setTitle(String title) {
1116 String oldValue = getTitle();
1117 this.title = title;
1118 firePropertyChange("title", oldValue, title);
1119 }
1120
1121
1122
1123
1124
1125
1126 protected boolean isTitleVisible() {
1127 return titleVisible;
1128 }
1129
1130
1131
1132
1133
1134
1135 protected void setTitleVisible(boolean titleVisible) {
1136 if (this.titleVisible == titleVisible) return;
1137 this.titleVisible = titleVisible;
1138 firePropertyChange("titleVisible", !titleVisible, titleVisible);
1139 }
1140
1141 protected boolean isResizable() {
1142 return resizable;
1143 }
1144
1145 protected void setResizable(boolean resizable) {
1146 if (this.resizable == resizable) return;
1147 this.resizable = resizable;
1148 firePropertyChange("resizable", !resizable, resizable);
1149 }
1150
1151
1152
1153
1154
1155
1156 protected int getTitleMaximumFontSize() {
1157 return titleMaximumFontSize;
1158 }
1159
1160
1161
1162
1163
1164
1165 protected void setTitleMaximumFontSize(int titleMaximumFontSize) {
1166 int oldValue = getTitleMaximumFontSize();
1167 this.titleMaximumFontSize = titleMaximumFontSize;
1168 firePropertyChange("titleMaximumFontSize", oldValue, titleMaximumFontSize);
1169 }
1170
1171
1172
1173
1174
1175
1176 protected int getTitleMinimumFontSize() {
1177 return titleMinimumFontSize;
1178 }
1179
1180
1181
1182
1183
1184
1185 protected void setTitleMinimumFontSize(int titleMinimumFontSize) {
1186 int oldValue = getTitleMinimumFontSize();
1187 this.titleMinimumFontSize = titleMinimumFontSize;
1188 firePropertyChange("titleMinimumFontSize", oldValue, titleMinimumFontSize);
1189 }
1190
1191
1192
1193
1194
1195 public String formatNumber(double x) {
1196 return formatter.sprintf(x);
1197 }
1198
1199
1200
1201
1202
1203
1204 public static void main(String[] args)
1205 {
1206 Thread t = new Thread() {
1207 public void run()
1208 {
1209 javax.swing.JFrame frame = new javax.swing.JFrame();
1210 frame.addWindowListener(new WindowAdapter() {
1211 public void windowClosing(WindowEvent e)
1212 {
1213 System.exit(0);
1214 }
1215 });
1216
1217 frame.setSize(new java.awt.Dimension(150, 120));
1218
1219 Gauger sp = new Gauger();
1220 sp.setLinearScale();
1221 sp.getRangedValue().setTickCalculator(new ManualTickCalculator(new double[]{5,50,100,500}, new double[]{5,50,100,500}, 100));
1222 sp.setScaleMode(Gauger.FIXED_SCALE);
1223 sp.setValue(-100, 500.0, 0);
1224 sp.setUnits("A");
1225 sp.setFormat("%d");
1226 frame.setContentPane(sp);
1227
1228 frame.setVisible(true);
1229
1230
1231 int i = 1;
1232
1233
1234
1235
1236 while (true) {
1237
1238
1239
1240 sp.setValue(Math.random() * 80 -40 );
1241
1242 try {
1243 i++;
1244
1245 if (i > 50) {
1246
1247
1248
1249
1250 i = 0;
1251 }
1252
1253 sleep(500);
1254 } catch (Exception e) {
1255 e.printStackTrace();
1256 }
1257 }
1258 }
1259 };
1260
1261 t.run();
1262 }
1263 }
1264
1265