CS 161 Homework 3 - Bar Graph Generator

Due Wed Sep 25 at 11:59pm

Overview

In this assignment, you will be writing a program that will generate simple bar graphs from a list of data points you provide. This is the same kind of program used in software like Excel!

Your program will use the terminal to solicit data values from the user: it will give the user a series of "prompts", and the user will type in the labels and values for each data point. The user should provide both a title for the graph, as well as labels and values for four (4) data points. An example interaction is shown below:

Welcome to the bar graph creator.
What is the title of your graph? Arbitrary Values
First data label: Alice
First data value: 8
Second data label: Bob
Second data value: 12
Third data label: Charles
Third data value: 3
Fourth data label: Doris
Fourth data value: 7
Generating graph...

The text in italics was typed in by the user.

After the user has entered this information, your program should display a window showing the bar graph. For example, the above entries would produce a graph similar to the following:

Some elements to notice about this window:

This assignment should be completed individually.

Objectives

Necessary Files

You will be creating your own program from scratch for this assignment---select "Project > New Project" from the BlueJ menu to create a new project.

You will need to download a copy of the README.txt (right-click on the link and select "Save Link As" to download the file) to fill out and turn in along with your assignment.

Also be sure to review relevant portions of the textbook: Chapters 2.9, 2.10, and 4.3.1.

Assignment Details

Below are some details and tips for developing your program. Note that the steps are not as explicit as in previous assignments---you should be able to develop this program on your own. But if you get stuck, you are welcome to ask for help!

  1. DO THIS FIRST: Before you read ahead, take a few minutes and think about how you would solve this problem! What classes do you think you'll need? What methods will they have? How might those methods fit together? Forming a mental model of how your program will work will make completing the assignment much easier!
  2. Your program should have two classes: a BarGraph class and a BarGraphGenerator class. The BarGraphGenerator class should be like a "tester" class--it has a main method that prompts the user for values using the Scanner, and then creates the window with the bar graph. The BarGraph class will be a drawing class like those described in Chapter 2.9 (though see below for some changes).
  3. Your BarGraphGenerator will need to use the Java Scanner to read user input.
    • Remember to import java.util.Scanner at the top of the class!
    • You will need to read in both text and numbers. You can read text by using the nextLine() method (which will read all the text until the end of the line--when the user hit "enter"--allowing labels to have multiple words). You can read numbers by using the nextInt() or nextDouble() methods. However remember that you will need to call readLine() after you read a number, so that there isn't a line break left floating in the scanner!
    • If you want to have the user's typed-in text appear on the same line as the prompt, you can use the System.out.print() method instead of System.out.println(). print() works exactly the same as println(), it just doesn't add a line break to the end.
    • Note that the terminal window will only pop-up when you call System.out.println(); make sure that you print a "prompt" for the user before demanding input! If you accidently close the terminal, you can reopen it by selecting "View > Show Terminal" from the BlueJ menu.
  4. Your BarGraph class should utilize the drawing template from the text: This will enable you to add a BarGraph object to a JFrame, and to draw shapes on it.
    • Remember to import the java.awt.* and javax.swing.* packages at the top of any classes where you use GUI components like JFrames, and java.awt.geom.* at the top of any class where you're drawing shapes.
    • Creating your JFrame will have one significant difference from the book's example. The book has you call the setSize() method on the frame in order to specify its size. However, this gives the size of the entire window including the title bar, etc. When we're drawing, we often care more about the size of our drawing area--that is, the size of the BarGraph.

      So rather than specify the size of the JFrame object, we will specify the desired size of the BarGraph object, and then tell Java to make the JFrame big enough to fit that drawing. We specify the desired size of the bar graph object with the following method call:

      barGraphObject.setPreferredSize(new Dimension(width,height));
      In this case, rather than passing in two ints for the size, the method has us create a new Dimension object, which is an object representing a set of dimensions (a width and a height)--the width and the height are specified when we create the dimension. This lets us tell Java how big the bar graph object should be. Note: 500x500 pixels is a good size for a BarGraph

      Finally, we tell Java to make the frame large enough to fit the BarGraph with the following method:

      frame.pack();
      We include this code immediately before we make the frame visible. This should let your frame fit your BarGraph, rather than forcing you to account for the (unknown) size of the window's title bar.
  5. I recommend you begin drawing your graph with "hard-coded" labels and values. Don't worry about doing it dynamically yet, just figure out the coordinates that makes your graph show up nicely. Once you have done that, you can "pull out" the coordinate numbers that might change and place them into variables. For example, if your code is:
    g2d.drawString("Hello World!", 10, 20);
    and you decide that the x-coordinate of that command will be variable, you can change your code to:
    int xCoord = 10;
    g2d.drawString("Hello World", xCoord, 20);
    This is called "refactoring" your code, and is a good way to add functionality once you have the basics in. Then you can just change what value you assign to the xCoord variable to make your code dynamic!
  6. You'll need to figure out the proper math to make your graph display dynamic (that is, to make sure that the axis labels are correct and that the bars are the correct height). This kind of math is very common in computer science--and is why this course fulfills a math requirement! A few tips:
    • In order to figure out the range for the y-axis, you'll want to find the maximum of your data values. There is a Math.max() function that gives you the maximum of 2 numbers... how can you use this method to find the maximum of 4 numbers? Think about how you might do it on paper!
    • Once you have the maximum value, you can figure out what numbers to put at each tick mark (dash) by taking the maximum range and dividing it into a number of portions.
    • In order to calculate the height of each rectangle, I recommend you calculate the number of "units" per pixel. If your maximum value is 20 and your graph is 400 pixels height, then each pixel is worth 20/400=0.05 units.
    • For drawing rectangles, once you have calculated the width and the height, you can subtract from where you want the "end" of the rectangle to be (on the bottom of the graph) to figure out the starting {x,y} coordinates.
  7. You can use whatever colors you like for the bars: you can use the constants from the Color class, or define your own Color objects using Color mycolor = new Color(redValue,greenValue,blueValue); where each value is a number between 0 and 255. If you want to pick a nice set of complementary colors, you might check out an online matching tool such as this or this, which will give you red/green/blue values. If you need help, let me know!
  8. Once you've got your graph being drawn correctly, you'll need to make sure that you can take the values from the user and give them to the BarGraph object. Because the BarGraph window may be redrawn multiple times (like if you cover it up and reveal it again), you'll need to store these variables in the object's state---that is, you'll need to make instance variables for them (we will discuss this in class; see also Chapter 3).

    • Remember to make your instance variables private!
    • You can have your graph use the instance variables in the draw method by referencing them as this.variableName

    After you've set up your instance variables, you'll need to define a constructor for your BarGraph. This constructor should take in all the user-specified variables as parameters, and then store them in the instance variables---and that's in!

    • We will talk about constructors in class, but possibly close to the assignment due date--you should make sure everything else works so that you can add in this final piece and turn in the assignment on time!
  9. Be sure and test your code as you write! Don't try and fix syntax errors or display bugs at the last minute; write a small piece of your program, then run it to make sure it works. And remember to test with multiple different sets of inputs!
  10. You should also include plenty of comments in your program--use them to explain your graph drawing math, to label sections of code, etc. Comments are about making your code readable and explaining why you wrote what you did.

Extensions

You can extend this assignment by adding extra decorations to your graph. Maybe dotted lines at each tick mark? Remember to use helper methods to break up your code if it gets complicated!

If you've got lots of time, you might try making a different kind of graph. Line graphs are pretty straightforward--but if you're feeling really adventurous, you can try to make a Pie Chart. You'll likely want to use the fillArc() method of the Graphics2D object.

Submitting Your Assignment

Grading

This assignment will be graded on approximately the following criteria: