Operating Systems project
Build an applet with an interface with a central panel and three buttons: Start, Stop, Add Ball.
The central panel should be an overloaded panel – a paint panel for drawing bouncing balls.
The project uses a Runnable interface and can add bouncing balls of different speeds, sizes and colors. When the balls collide, they should bounce “off” each other.
After you get code below working, you’ll realize it is probably the balls that need to be runnable, and that you need to solve the problem of the paintpanel “knowing” where the balls are and when to repaint them, so substantial refactoring will be needed.
Aside – not a requirement for completion: To minimize flickering on repaint, a variety of methods can be pursued. Below, in paint, I use super.paintComponent(g);
to erase the old image. This is really overkill. Less painting is involved if you just paint the ball in its old position with the background color before repainting in the new position with the foreground color. It is also possible to double - or triple - buffer the image. This involves “getting” another Image, using its graphics to draw on it “offscreen”, and then, in paint, just swapping the onscreen for the offscreen image. I probably won’t teach you how to do this because of time considerations, but it is easy to find code, and I can give you sample code if you ask.
Here is a “starter” program… a single bouncing ball.
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
public class Bouncy extends JApplet {
PaintPanel center;
public void init(){
center=new PaintPanel(getWidth(),getHeight());
getContentPane().add(center,BorderLayout.CENTER);
ExecutorService threadrunner=Executors.newFixedThreadPool(1);
threadrunner.execute(center);
}
class PaintPanel extends JPanel implements Runnable{
int x,y,xinc,yinc,MAXX,MAXY;
public PaintPanel(int w,int h){
x=y=100;
MAXX=w;
MAXY=h;
xinc=yinc=1;
}//constructor
public void paint(Graphics g){
super.paintComponent(g);
g.setColor(Color.red);
g.fillOval(x,y,50,50);
}
public void run(){
while(true){
try{
Thread.sleep(10);
}
catch(InterruptedException e){}
if(x<=2||x>=MAXX-50)xinc=-xinc;
if(y<=2||y>=MAXY-50)yinc=-yinc;
x+=xinc;
y+=yinc;
System.out.println("in loop x= y="+x+" "+y);
repaint();
}//while
}//run
}//inner paintpanel
}//outer
Aside on SwingUtilities... You likely won’t need this BUT if you plan need to update textfields/labels for trace purposes, or use the applet’s paint method, use SwingUtilities.invokeLater, so as not to interfere with a threads’ execution/order of updates. (You put the repaint/refresh code in a special block) This uses the event dispatching thread to decide when it should do the updating.
SwingUtilities.invokeLater(
New Runnable(){
public void run(){
//update textfields or labels or use graphics to draw lines HERE
}});