CISC181 F2017 JFrameExample

From class_wiki
Jump to: navigation, search

Main class

 package cisc181.mylab_2;

 // Christopher Rasmussen

 import javax.swing.JFrame;

 public class Lab2 {

     public static void main(String[] args) {

       JFrame myFrame = new JFrame();

       myFrame.setSize(500, 500);
       myFrame.setTitle("Color Test");
       myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

       ColorJComponent myComponent = new ColorJComponent(500, 500);
       myFrame.add(myComponent);

       myFrame.setVisible(true);   // setVisible() *after* add() is the norm
     }
 }
 

Custom JComponent class

 package cisc181.mylab_2;

 // Christopher Rasmussen

 import javax.swing.JComponent;
 import java.util.Random;
 import java.awt.Graphics;

 public class ColorJComponent extends JComponent {
       
   int[] circleX;
   int[] circleY;
   int[] circleR;
   final int MIN_RADIUS = 5;
   final int MAX_RADIUS = 15;
   final int MIN_SEPARATION = 1;
   final int MAX_ATTEMPTS = 5000;
   final int MAX_CIRCLES = 1000;
   Random rand;
   int initialWidth;
   int initialHeight;
   int numCircles;   // actual number of circles drawn

   // are circles at index i and index j separated by *<= tolerance* pixels?

   boolean twoCirclesOverlap(int i, int j, int tolerance) {
     double distanceBetweenCenters =
         Math.sqrt((circleX[i] - circleX[j]) * (circleX[i] - circleX[j]) +
                   (circleY[i] - circleY[j]) * (circleY[i] - circleY[j]));
     return (distanceBetweenCenters <= (circleR[i] + circleR[j] + tolerance));
   }

   // are any existing circles separated from the proposed one at index i by *<= tolerance* pixels?

   boolean anyCirclesOverlap(int i, int tolerance) {
     for (int j = 0; j < i; j++) {
       if (twoCirclesOverlap(i, j, tolerance)) {
         return true;
       }
     }
     return false;
   }

   // attempt to randomly place the largest-possible circle that does not overlap any existing one

   boolean tryToPlaceCircle(int i) {

     for (int j = 0; j < MAX_ATTEMPTS; j++) {

       // pick a random position, set initial radius to minimum

       circleX[i] = rand.nextInt(initialWidth);
       circleY[i] = rand.nextInt(initialHeight);
       circleR[i] = MIN_RADIUS;

       // grow circle until it touches another or reaches max size

       while (!anyCirclesOverlap(i, MIN_SEPARATION) && circleR[i] < MAX_RADIUS)
         circleR[i]++;

       // it was touching from the start -- must try again

       if (circleR[i] == MIN_RADIUS) {
         continue;
       }

       // grew to max size -- well done

       else if (circleR[i] == MAX_RADIUS) {
         return true;
       }

       // grew some, but then touched

       else {
         circleR[i]--;   // retract to the step before touch
         return true;
       }
     }

     // all attempts failed

     return false;
   }

   ColorJComponent(int width, int height) {

     circleX = new int[MAX_CIRCLES];
     circleY = new int[MAX_CIRCLES];
     circleR = new int[MAX_CIRCLES];

     initialWidth = width;
     initialHeight = height;

     rand = new Random();

     numCircles = 0;
     while (numCircles < MAX_CIRCLES && tryToPlaceCircle(numCircles)) {
       numCircles++;
     }
   }

   public void paintComponent(Graphics g) {

     for (int i = 0; i < numCircles; i++) {
       g.drawOval(circleX[i] - circleR[i], circleY[i] - circleR[i], 2 * circleR[i], 2 * circleR[i]);
     }
   }
 }