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]

Reply via email to