Using SwingUtilities.invokeAndWait()

Chapter 9 - Threads and Swing

Java Thread Programming
Paul Hyde
  Copyright 1999 Sams Publishing

Floating Components Around Inside a Container
CompMover (see Listing 9.11) is a utility that takes a component and an initial position and moves the component around inside its container. This is basically a demonstration of how animation can be achieved by moving components.
Listing 9.11  CompMover.javaA Utility to Float Components Around Inside a Container
  1: import java.awt.*;
  2: import javax.swing.*;
  3:
  4: public class CompMover extends Object {
  5:     private Component comp;
  6:     private int initX;
  7:     private int initY;
  8:     private int offsetX;
  9:     private int offsetY;
10:     private boolean firstTime;
11:     private Runnable updatePositionRun;
12:
13:     private Thread internalThread;
14:     private volatile boolean noStopRequested;
15:
16:     public CompMover(Component comp,
17:                 int initX, int initY,
18:                 int offsetX, int offsetY
19:            ) {
20:
21:         this.comp = comp;
22:         this.initX = initX;
23:         this.initY = initY;
24:         this.offsetX = offsetX;
25:         this.offsetY = offsetY;
26:
27:         firstTime = true;
28:
29:         updatePositionRun = new Runnable() {
30:                 public void run() {
31:                     updatePosition();
32:                 }
33:             };
34:
35:         noStopRequested = true;
36:         Runnable r = new Runnable() {
37:                 public void run() {
38:                     try {
39:                         runWork();
40:                     } catch (Exception x) {
41:                         // in case ANY exception slips through
42:                         x.printStackTrace();
43:                     }
44:                 }
45:             };
46:
47:         internalThread = new Thread(r);
48:         internalThread.start();
49:     }
50:
51:     private void runWork() {
52:         while (noStopRequested) {
53:             try {
54:                 Thread.sleep(200);
55:                 SwingUtilities.invokeAndWait(updatePositionRun);
56:             } catch (InterruptedException ix) {
57:                 // ignore
58:             } catch (Exception x) {
59:                 x.printStackTrace();
60:             }
61:         }
62:     }
63:
64:     public void stopRequest() {
65:         noStopRequested = false;
66:         internalThread.interrupt();
67:     }
68:
69:     public boolean isAlive() {
70:         return internalThread.isAlive();
71:     }
72:
73:     private void updatePosition () {
74:         // should only be called by the *event* thread
75:
76:         if (!comp.isVisible()) {
77:             return;
78:         }
79:
80:         Component parent = comp.getParent();
81:         if (parent == null) {
82:             return;
83:         }
84:
85:         Dimension parentSize = parent.getSize();
86:         if ((parentSize == null) &&
87:              (parentSize.width < 1) &&
88:              (parentSize.height < 1)
89:           ) {
90:
91:             return;
92:         }
93:
94:         int newX = 0;
95:         int newY = 0;
96:
97:         if (firstTime) {
98:             firstTime = false;
99:             newX = initX;
100:             newY = initY;
101:         } else {
102:             Point loc = comp.getLocation();
103:             newX = loc.x + offsetX;
104:             newY = loc.y + offsetY;
105:         }
106:
107:         newX = newX % parentSize.width;
108:         newY = newY % parentSize.height;
109:
110:         if (newX < 0) {
111:             // wrap around other side
112:             newX += parentSize.width;
113:         }
114:
115:         if (newY < 0) {
116:             // wrap around other side
117:             newY += parentSize.height;
118:         }
119:
120:         comp.setLocation(newX, newY);
121:         parent.repaint();
122:     }
123:
124:     public static void main(String[] args) {
125:         Component[] comp = new Component[6];
126:
127:         comp[0] = new ScrollText(Scrolling Text);
128:         comp[1] = new ScrollText(Java Threads);
129:         comp[2] = new SlideShow();
130:         comp[3] = new SlideShow();
131:         comp[4] = new DigitalTimer();
132:         comp[5] = new DigitalTimer();
133:
134:         JPanel p = new JPanel();
135:         p.setLayout(null); // no layout manager
136:
137:         for (int i = 0; i < comp.length; i++) {
138:             p.add(comp[i]);
139:
140:             int x = (int) (300 * Math.random());
141:             int y = (int) (200 * Math.random());
142:             int xOff = 2 - (int) (5 * Math.random());
143:             int yOff = 2 - (int) (5 * Math.random());
144:
145:             new CompMover(comp[i], x, y, xOff, yOff);
146:         }
147:
148:         JFrame f = new JFrame(CompMover Demo);
149:         f.setContentPane(p);
150:         f.setSize(400, 300);
151:         f.setVisible(true);
152:     }
153: }
The constructor for CompMover (lines 1649) takes a component, an initial position, and x and y offset information. A Runnable is created (lines 2933) to be passed to SwingUtilities.invokeAndWait() . This Runnable is referred to by updatePositionRun and invokes the updatePosition() when called by the event thread. The rest of the constructor gets the internal thread up and running.
The internal thread invokes runWork() (lines 5162), where it loops inside the while until another thread invokes stopRequest() . Inside the while loop, the thread sleeps for 0.2 seconds and then invokes SwingUtilities.invokeAndWait() passing in updatePositionRun (lines 5455). updatePositionRun causes the event thread to invoke updatePosition() .
Each time that the event thread calls updatePosition() (lines 73122), the event thread attempts to move the component a little. Several checks are done to be sure that the parent container is accessible (lines 7692). The current location of the component is retrieved and the x and y offsets are added to determine the new location (lines 97118). The event thread proceeds to invoke setLocation() on the component to move it to its new position (line 120). The event thread then invokes repaint() on the parent container to get the move to show up (line 121).
In main() (lines 124152), a number of components are constructed : two instances of ScrollText , two instances of SlideShow , and two instances of DigitalTimer (lines 125132). A panel is created to house these components, and it has its layout manager set to null because CompMover is taking care of component positions (lines 134135). Inside the for loop (lines 137146), each component is added to the panel (line 138) and has its initial position and x and y offsets randomly determined (lines 140143). Each component also gets handed off to a new instance of CompMover to handle its positioning (line 145).
Each of the six components has an internal thread running within it to handle its animation. In addition, each of the six instances of CompMover also has an internal thread running to handle the component movement. All 12 of these threads perform many operations per second and can bog down the processor. If you dont have a really fast machine, you might notice some sluggishness when you run this example. As you can see, animation is very processor- intensive .
Figure 9.14 shows how CompMover looks after running for about 75 seconds. Figure 9.15 shows how it looks after about 136 seconds. Each of the components travels around in a different direction. When a component moves off one side of the screen, it returns on the other side. Your output will differ significantly because the initial positions and directions of movement for the components are randomly determined.
Figure 9.14: A snapshot of CompMover in action.
Figure 9.15: Another snapshot of CompMover after more time has passed.

Toc


Java Thread Programming
Java Thread Programming
ISBN: 0672315858
EAN: 2147483647
Year: 2005
Pages: 149
Authors: Paul Hyde

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net