Hi, I wrote small animation application which uses multiple threads and I have some problems running it on my Linux machine. Generally, I do the following: 1. In one thread I calculate my image using MemoryImageSource method (time-consuming task). 2. Stop and start my Animation using buttons. 3. Close the window while animation loop is running. I implemented it using InvokeLater() method. The animation loop calls AnimatedImage calculation routine and after that uses InvokeLater() method according to Java Tutorial suggestion. I also used thread interruption method to stop the tread. On Linux with Blackdown JDK with green threads my stop button does not work. It cannot get the control - my application is always busy doing animation image calculations and does not give up the control. I also cannot close the application window when my animation is running. I can do everything on Win98 and with native threads. iHowever, when I run it with native threads it complains in init() method: Exception occurred during event dispatching: java.lang.NullPointerException at sun.awt.image.BufferedImageGraphics2D.drawImage(Compiled Code) at AnimationPanel.paintComponent(Compiled Code) at javax.swing.JComponent.paint(Compiled Code) at javax.swing.JComponent.paintChildren(Compiled Code) at javax.swing.JComponent.paint(Compiled Code) at javax.swing.JComponent.paintChildren(Compiled Code) at javax.swing.JComponent.paint(Compiled Code) at javax.swing.JComponent.paintChildren(Compiled Code) at javax.swing.JComponent.paint(Compiled Code) at javax.swing.JLayeredPane.paint(Compiled Code) at javax.swing.JComponent.paintChildren(Compiled Code) at javax.swing.JComponent.paint(Compiled Code) at java.awt.Container.paint(Compiled Code) at sun.awt.motif.MComponentPeer.handleEvent(Compiled Code) at java.awt.Component.dispatchEventImpl(Compiled Code) at java.awt.Container.dispatchEventImpl(Compiled Code) at java.awt.Window.dispatchEventImpl(Compiled Code) at java.awt.Component.dispatchEvent(Compiled Code) at java.awt.EventQueue.dispatchEvent(Compiled Code) at java.awt.EventDispatchThread.run(Compiled Code) I could use SwingWorker class, but I thought there is simpler solution without it. Here is my code (I could not make it shorter). It compiles and runs on Linux RedHat 6.0, 2.2.5-15 version, I use Blackdown JDK 1.2. My machine is Pentium III, 500MGZ and I have 192 MB of main memory. For Linux I run it with green threads using -green option. On Win98 I use SUN's JDK 1.2.1. without -green. If you think I designed it wrongly, please, tell me so. I am not very experienced in Threads. Thank you, Jacob Nikom PS: I put some print statements to trace the execution better //=========== beginning of the file ThreadPanel.java ================== import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; class ThreadPanel extends JPanel implements Runnable { static AnimationPanel animationPanel; JButton startButton; JButton stopButton; Color backgroundColor = new Color(0.433f,0.691f,0.641f); Border spaceBelow = BorderFactory.createEmptyBorder(0, 0, 5, 0); public Thread videoThread = null; // simply very big variable to continue the loop forever int NUMLOOPS = 1000000000; // Drawing speed control variable - the smaller the faster drawing int INVERTED_DRAWING_SPEED = 10; ThreadPanel() { super(); System.out.println("Start ThreadPanel consructor"); this.setLayout(null); this.setBounds(0,0, 200,200); this.setBackground(Color.blue); startButton = new JButton("Start"); startButton.setBounds(5,5, 100, 30); startButton.setBackground(Color.green); startButton.addActionListener(startListener); startButton.setEnabled(true); stopButton = new JButton("Stop"); stopButton.setBounds(5,40, 100, 30); stopButton.setBackground(Color.red); stopButton.addActionListener(stopListener); stopButton.setEnabled(false); animationPanel = new AnimationPanel(); animationPanel.setSize(200,200); animationPanel.setBounds(5,80, 100,100); animationPanel.setBackground(new Color(0.433f,0.691f,0.641f)); animationPanel.setForeground(new Color(0.001f,0.300f,0.900f)); this.add(startButton); this.add(stopButton); this.add(animationPanel); System.out.println("Finish ThreadPanel consructor"); } // Typical threaded applet start and stop public void start() { System.out.println("Start start"); if (videoThread == null) { videoThread = new Thread(this, "Cycle"); videoThread.start(); } System.out.println("Finish start"); } public void stopThread() { System.out.println("Start stopThread"); videoThread = null; System.out.println("Finish stopThread"); } // Continually run public void run() { int i = 0; System.out.println("Start run"); Thread myCurrentThread = Thread.currentThread(); try { while (videoThread == myCurrentThread) { // image calculating thread animationPanel.cyclingImage(); // Passing the control to the event-dispatching thread Runnable doDrawPanel = new Runnable() { public void run() { } }; SwingUtilities.invokeLater(doDrawPanel); if (videoThread.interrupted()) { throw new InterruptedException(); } System.out.println("i = "+i); i++; } } catch (InterruptedException e) { stopThread(); System.out.println("Interrupted"); } System.out.println("Finish run"); } ActionListener startListener = new ActionListener() { public void actionPerformed(ActionEvent event) { System.out.println("Start startListener"); startButton.setEnabled(false); stopButton.setEnabled(true); start(); System.out.println("Finish startListener"); } }; ActionListener stopListener = new ActionListener() { public void actionPerformed(ActionEvent event) { System.out.println("Start stopListener"); stopButton.setEnabled(false); videoThread.interrupt(); startButton.setEnabled(true); System.out.println("Finish stopListener"); } }; public void paintComponent(Graphics g) { super.paintComponent(g); //clears the background } public static void main(String[] args) { JFrame frame = new JFrame("Swing Worker Thread Motion Example"); frame.setSize(300, 300); frame.setLocation(0,0); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.out.println("windowClosing"); System.exit(0); } }); Container container = frame.getContentPane(); container.setLayout(null); ThreadPanel threadPanel = new ThreadPanel(); threadPanel.setSize(200, 200); threadPanel.setLocation(0, 0); container.add(threadPanel); frame.setVisible(true); frame.validate(); animationPanel.init(); } } //=========== end of the file ThreadPanel.java ================== //=========== beginning of the file AnimationPanel.java ================== import javax.swing.*; import java.applet.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; // This applet creates a series of moving // lines by creating a memory image and cycling // its color palette. public class AnimationPanel extends JPanel { public Image cycledImage; // image after cycling public static int ii = 0; public static int imageWidth = 100; public static int imageHeight = 100; public int alpha = 255, red = 255, green = 255, blue = 255; int index = 0; int pixels[]; AnimationPanel() { super(); this.setLayout(null); } public void init() { // ("Start init"); // Create space for the memory image pixels = new int[imageWidth * imageHeight]; // Now create the image, just go from top to bottom, left to right // filling in the colors from 1-16 and repeating. alpha = 255; red = 255; green = 255; blue = 0; for (int i=0; i < imageHeight; i++) { for (int j=0; j < imageWidth; j++) { pixels[index++] = (alpha << 24) | (red << 16) | (green << 8) | blue; } } // Create the cycled image cycledImage = createImage( new MemoryImageSource(imageWidth, imageHeight, pixels, 0, imageWidth)); // ("Finish init repaintCall = "); } // Paint simply draws the cycled image public void paintComponent(Graphics g) { System.out.println("In paintComponent"); g.drawImage(cycledImage, 0, 0, this); } // Cycles the colors and creates a new cycled image. Uses media // tracker to ensure that the new image has been created before // trying to display. Otherwise, we can get bad flicker. public synchronized void cyclingImage() { int jj = 0; cycledImage.flush(); jj = ii%111; alpha = 255; red = 0; green = 0; blue = 255; index = 0; for (int i = 0; i < imageHeight; i++) { for (int j = 0; j < imageWidth; j++) { red = 255 - jj*2; green = j*2 + jj/2; blue = jj + j; pixels[index++] = (alpha << 24) | (red << 16) | (green << 8) | blue; } } System.out.println("In cyclingImage ii ="+ii+" jj = "+jj); ii++; // Create the cycled image cycledImage = createImage( new MemoryImageSource(imageWidth, imageHeight, pixels, 0, imageWidth)); // Flush clears out a loaded image without having to create a // while new one. When we use waitForID on this image now, it // will be regenerated. MediaTracker myTracker = new MediaTracker(this); myTracker.addImage(cycledImage, 0); try { // Cause the cycledImage to be regenerated if (!myTracker.waitForID(0, 1000)) { return; } } catch (Exception ignore) { } repaint(); } } //=========== end of the file AnimationPanel.java ================== ---------------------------------------------------------------------- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]