[an error occurred while processing this directive]
Synchronized
[an error occurred while processing this directive]
       Race1.java      Race2.java     All lectures

If synchronized is not used, painting is messed up

Hit Reset then Start
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.applet.*;

class Dot1 {
   int left, top;
   Color color;
   String labl;
   Font fnt;

   Dot1 (String lbl, int l, int t, Color c, Font f) {
      labl   = lbl;
      left   = l;
      top    = t;
      color  = c;
      fnt    = f;
   }

   public void draw (Graphics q) {}

   public boolean find (int x, int y) { return false; }
}

class RectDot1 extends Dot1 {
   int width, height;

   RectDot1 (String s, int l, int t, int w, int h, Color c, Font f) {
      super(s,l,t,c,f);
      width = w;
      height = h;
   }

   public boolean find(int x, int y) {
      if (super.left < x && x < super.left + width &&
          super.top < y  && y < super.top + 2*height)
         return true;
      return false;
   }

   public void draw(Graphics g) {
      g.setFont(super.fnt);
      int w = 20;
      int h = 10;
      g.setColor(color);
      g.fillRect(left, top, width, height);
      g.setColor(Color.black);
      g.drawString(labl, left-w/2+width/2, top+h/4+height/2);
   }
}

class Mov1 extends Thread {
   Race1Frame t1;
   double i = 0;
   int width;
   JPanel mp;
   int dot;
   
   public Mov1 (int w, Race1Frame t, int d, JPanel g) {  
      width = w;  t1 = t; dot = d; mp = g; 
   }
   
   public void run () {
      int multiplier = 5;
      while (i < width*1000*multiplier) {
         i++;
         if ((i+500*dot)%1000 == 0) {
            t1.setDot(dot, (int)(i/(multiplier*1000))+30);
            t1.update(mp.getGraphics());
         }
      }
   }
   
   public int valueOf() { return (int)(i/1000); }
}

class Race1Frame extends JFrame implements ActionListener, AdjustmentListener {
   JButton reset, start;
   JPanel mainpanel;
   Dot1 dot[] = new Dot1[4];
   Mov1 mov[] = new Mov1[4];
   int pre[] = new int[4];
   JScrollBar scr[] = new JScrollBar[4];
   JTextField txt[] = new JTextField[4];
   Color dotcolor = Color.red;
   Font myfont = new Font("TimesRoman", Font.PLAIN, 18);
   boolean running = false;

   public Race1Frame () {
      setLayout(new BorderLayout(20,20));
      JPanel q = new JPanel();
      q.setLayout(new BorderLayout());
      JPanel p = new JPanel();
      p.setLayout(new GridLayout(3,3,20,20));
      p.add(new JLabel(""));
      p.add(start = new JButton("Start"));
      p.add(new JLabel(""));
      p.add(new JLabel(""));
      p.add(reset = new JButton("Reset"));
      p.add(new JLabel(""));
      p.add(new JLabel(""));
      p.add(new JLabel(""));
      p.add(new JLabel(""));
      q.add("West", p);
      JPanel t = new JPanel();
      t.setLayout(new BorderLayout());
      JPanel r = new JPanel();
      r.setLayout(new GridLayout(4,1,10,10));
      for (int i=0 ; i < 4 ; i++) {
         r.add(scr[i] = new JScrollBar(JScrollBar.HORIZONTAL, 1, 1, 1, 5));
         scr[i].setValue(3);
         scr[i].addAdjustmentListener(this);
         pre[i] = 3;
      }
      JPanel s = new JPanel();
      s.setLayout(new GridLayout(4,1,10,10));
      for (int i=0 ; i < 4 ; i++) {
         s.add(txt[i] = new JTextField(4));
         txt[i].setEditable(false);
         txt[i].setBackground(Color.white);
         txt[i].setText(String.valueOf(pre[i]));
      }
      t.add("Center", r);
      t.add("East", s);
      q.add("Center", t);
      add("South", q);
      mainpanel = new JPanel();
      add("Center", mainpanel);
      for (int i=0; i < 4 ; i++)
         dot[i] = new RectDot1("", 30, 40*i+30, 10, 25, Color.blue, myfont);
      reset.addActionListener(this);
      start.addActionListener(this);      
   }

   Image offscreen;
   Dimension offscreensize;
   Graphics offgraphics;

   // Here is the difference
   /* synchronized */ public void update(Graphics g) {
      Dimension d = getSize();
      if ((offscreen == null) || (d.width != offscreensize.width) ||
          (d.height != offscreensize.height)) {
         offscreen = createImage(d.width, d.height);
         offscreensize = d;
         offgraphics = offscreen.getGraphics();
         offgraphics.setFont(getFont());
      }

      offgraphics.setColor(new Color(200, 230, 240));
      offgraphics.fillRect(0, 0, d.width, d.height);
      
      offgraphics.setColor(Color.black);
      offgraphics.fillRect(30, 39, d.width-60, 2);
      offgraphics.setColor(Color.black);      
      offgraphics.fillRect(30, 79, d.width-60, 2);
      offgraphics.setColor(Color.black);      
      offgraphics.fillRect(30,119, d.width-60, 2);
      offgraphics.setColor(Color.black);      
      offgraphics.fillRect(30,159, d.width-60, 2);      

      for (int i=0 ; i < 4 ; i++) dot[i].draw(offgraphics);
      g.drawImage(offscreen, 0, 0, null);
   }

   public void actionPerformed (ActionEvent evt) {
      if (evt.getSource() == reset) {
         Dimension d = getSize();
         int wid = d.width;
         for (int i=0 ; i < 4 ; i++) {
            if (mov[i] != null) mov[i].stop();
            dot[i].left = 30;
            mov[i] = new Mov1(wid-60, this, i, mainpanel);
            mov[i].setPriority(scr[i].getValue());
            pre[i] = scr[i].getValue();
         }
         update(mainpanel.getGraphics());         
      }
      if (evt.getSource() == start) {
         try {
            for (int i=0 ; i < 4 ; i++) mov[i].start();
         } catch (Exception e) {
            System.out.println("Thread already started");
         }
      }
   }
   
   public void adjustmentValueChanged (AdjustmentEvent evt) {
      for (int i=0; i < 4 ; i++) {
         int k = scr[i].getValue();
         if (pre[i] != k) {
            txt[i].setText(String.valueOf(k));
            try {  mov[i].setPriority(k);  } catch (Exception e) {}
         }
         pre[i] = k;
      }
   }

   public void setDot (int d, int w) { dot[d].left = w; }
}

public class Race1 extends Applet {
   public void init () {
      Race1Frame race = new Race1Frame();
      race.setSize(600,350);
      race.setVisible(true);
   }
}