Homework 2 Hints
1. Thermometer Application:
For each of the 3 views and the temperature control slider, you can
specify the position by using
setLocation(x,y);
This will allow you to space out the windows so they won't be on top of
each other upon running your code.
1. b. Use an Area object to create the filled bulb and stem:
You actually won't use fillOval or fillRect.
You will create Area
objects for each of the stem and bulb, then take their union and display
the Area resulting from that union. The pseudocode might be something
like:
create a 2D rectangle object for the stem, passing in x, y, width,
height
create a 2D ellipse object for the bulb, passing in x, y, width, height
create an area object for the stem, passing in the 2D rectangle for stem
create an area object for the bulb, passing in the 2D ellipse for bulb
augment the stem area by adding the bulb area to it as in
stemarea.add(bulbarea);
display the augmented stem area with fill()
Of course, you'll have to specify what x, y, width,
and height are.
When I say "passing in", I mean passing in to the constructor for the
respective graphics class (rectangle, ellipse, area).
You can use a similar technique for part 4 of the homework.
Be sure to use Graphics2D by adding
Graphics2D g2 = (Graphics2D)g;
to the beginning of paintComponent() and use
g2 for all the drawing.
Be sure "import java.awt.geom.*;" is at the top of the code
file.
1.c.a. Gauge view with arrow:
To get a chorded half oval, you can draw an Arc2D.Double,
where its
arguments are x, y, width, height, 0, 180,
and Arc2D.CHORD.
Drawing the line and arrow (needle):
This is my way of doing it, which will mean that Brad's equations need
to be altered slightly, as I will point out later. Given the tail point
of the needle (the center of the oval) (P1), the length of the
needle
line, and the angle, I will derive the point at the tip (P2).
It is acceptable to use a fixed needle length, you don't have to adjust
the length to fit perfectly in the oval.
To calculate dx and dy:
dx = needlelength*cos(angle)
dy = needlelength*sin(angle)
needlelength is line_length in Brad's
equations.
angle is computed based on the current temperature. Be
sure to convert
the angle to RADIANS when using Math.sin and
Math.cos.
Given P1 (x1 and y1), then to calculate the point
at the tip, P2:
x2 = x1 + dx
y2 = y1 - dy
You can now simply draw a line, passing in x1,
y1,
x2, and y2. This will be the needle line
(without the arrow head).
Then to get the arrow:
normdx = dx/needlelength
normdy = dy/needlelength
Choose a suitable arrowlength and arrowwidth.
Then calculate the endpoints of the arrow with these equations:
arrowx1 = x2 - arrowlength * normdx - arrowwidth * normdy
arrowy1 = y2 + arrowlength
* normdy - arrowwidth *
normdx
arrowx2 = x2 - arrowlength * normdx + arrowwidth * normdy
arrowy2 = y2 + arrowlength
* normdy + arrowwidth *
normdx
Note the 4 highlighted + and - signs in the equations for
arrowy1 and arrowy2 that are flipped
from what they were in Brad's equations.
Now create an array of xpoints and an array of
ypoints. The first point
is (arrowx1, arrowy1), the second is (x2,
y2), and the third is (arrowx2, arrowy2).
Call both drawPolygon and fillPolygon, passing
in xpoints, ypoints, and
the number of points (3). Calling both functions will make the
arrowhead look a little nicer.
1.c.b. Filled pie arc view:
Be sure the amount to fill the arc is based on 360 degrees, and not 180
degrees.
Temperature controller code:
The two arguments to pass in are the model variable and new
JFrame().
The slider code has a good example of how to integrate the controller
code with the rest of your thermometer code. In particular, the parts
about observers, setValue() in
SliderModel.java and
valueChanged() in
SliderGraphicalView.java and Slider.java. The
slider code can be found here:
http://www.cs.utk.edu/~bvz/gui/notes/javaGraphics/index.html
2. DisplayImage:
There is a good example of code that displays an image at:
http://www.cs.utk.edu/~bvz/gui/notes/javaGraphics/index.html
Of course, after drawing the image, you will need to add code to write
the caption under it. You can use the same technique as in the
thermometer code for HW 1. To center the text underneath the image, the
starting position of the text will be based on the width and height of
the image.
3. DisplayTile:
There is a code example in the lecture notes at:
http://www.cs.utk.edu/~bvz/gui/notes/texture.java
It shows how to create a buffered image and a TexturePaint
object.
After the code for creating an ImageIcon from the image,
and before
creating a buffered image, add the code for scaling the image. First
use getScaledInstance() of the Image class to
get a scaled version of
the image. The third argument can just be a 1. After this, create an
ImageIcon from the scaled image with
Image scaledimage2 = new ImageIcon(scaledimage).getImage()
where scaledimage is the image resulting from
getScaledInstance(). If
you don't include the above line of code, the image will not display on
the Ubuntu machines.
Also, on the Ubuntu machines, if your window size is the same size as
the rectangle (210x50), the image tiling will not fill the entire
window. Don't worry about this, it is an issue with Java, not your
code.
4. Composite object using Area class:
Use the technique outlined in 1.b., which discusses creating the stem
and bulb of the thermometer. There are a couple ways you can do this.
One way is to keep augmenting the same Area object with successive
intersections, unions, xors, or differences of other Area objects and
draw the entire object at the end. However, if you want different parts
to be different colors, this won't work, as it will draw the entire
object in the most recently set color. If you want to use different
colors, then you can draw portions of the object in increments, and
change colors inbetween. Either way is acceptable. A good example that
displays a pear is at
http://java.sun.com/docs/books/tutorial/2d/advanced/complexshapes.html
The object you create doesn't need to be this sophisticated, but it
shows you the idea.
5. Function plotter:
You do not need to worry about the case where all of a, b,
and c are 0, that is, the function degenerates to a horizontal
line. This is a special case that makes the problem more complicated
than it needs to be.
Below is some pseudocode that shows how to use the
GeneralPath class and
draw a curve. Assuming you have an array of xpoints and an
array of
ypoints that make up the curve, the algorithm is:
create a new GeneralPath variable, say "curve", with arguments
GeneralPath.WIND_EVEN_ODD and xpoints.length
curve.moveTo(xpoints[0], ypoints[0])
for index from 1 to xpoints.length-1
curve.lineTo(xpoints[index], ypoints[index])
g2.draw(curve)
This algorithm came from an example in the Java tutorial at this link:
http://java.sun.com/docs/books/tutorial/2d/geometry/arbitrary.html