Title: Lecture 17: More Arrays
1Lecture 17 More Arrays
2More on Casting
- Earlier in the semester, we learned how to
convert doubles to ints - This will make number equal to 4.
- This works for types other than int and double,
as well
double d 4.5678 int number (int)d
3More on Casting
- On a JComboBox, the addItem() method is defined
like this - And getSelectedItem is defined like this
- This is flexible, because we can put anything
into the JComboBoxs menu - The trouble is we can only get an Object out
public void addItem(Object item)
public Object getSelectedItem()
4More on Casting
- In the case of JComboBox, we know the type of the
objects we put in via addItem() - Usually its a String
- Perhaps a Font
- You could do this for your TextPlay assignment
- We can then cast them back to what they were when
we get them out - We can now treat item like its a String, and
were not restricted to only the methods of
Object.
fontChoice.addItem(Courier New)
String item (String)fontChoice.getSelectedIt
em()
5More on Casting
- You can do the same thing with Font objects
- Adding
- Retrieving
- This will work for any type, so long as you get
the type right - If you cast something and its not actually that
type, Java will give you a ClassCastException.
Font insertedFont . . .
fontChoice.addItem(insertedFont)
Font font (Font)fontChoice.getSelectedItem()
6Simple Drawing Program
- Weve got a really simple drawing program
- Can make new shapes
- Can select what shape and what color via
JComboBoxes - One new feature
- We can select and drag any shape on the canvas
7Simple Drawing Program
- To select and drag any shape, we need to be able
to remember all the objects - We need to call contains() on all of them to see
which one the mouse was in - Well store each object in an array when we draw
it - When we need an object again, we can go through
the array and find it there.
8Arrays Finite size
- Arrays have to be constructed with a size, so
when we build our program, we have to specify a
maximum number of objects to create - Well make this the size of our array
public class Drawing extends WindowController
// max number of objects to be displayed
private static final int MAX_OBJECTS 20
. . .
public class Drawing extends WindowController
// max number of objects to be displayed
private DrawableInterface geomObject
new DrawableInterfaceMAX_OBJECTS . .
.
9Arrays of Interface types
- Notice that we declared our array as an array of
DrawableInterfaces - Recall that this is an interface for all the
different graphical objects in ObjectDraw. - We can thus store any kind of shape in this array
- FilledRects, FilledOvals, VisibleImages, etc.
- Like any array of Objects, everything in this
array starts out as null - Well need to initialize the elements before we
use them
public class Drawing extends WindowController
// max number of objects to be displayed
private DrawableInterface geomObject
new DrawableInterfaceMAX_OBJECTS . .
.
10Keeping track of elements
- Well need to keep track of how many elements
there are in the array - Well fill the array from the 0th slot up to the
end - If we keep track of this number, well know that
exactly that many elements in the array are
non-null - Well increment this number whenever we add a new
shape
public class Drawing extends WindowController
// max number of objects to be displayed
private DrawableInterface geomObject
new DrawableInterfaceMAX_OBJECTS
// number of objects added to the array
private int numObjects 0 . . .
11onMousePress
- In onMousePress, we just check to see what mode
were in - If the JComboBox says were adding, well add
- If the JComboBox says were selecting, well
select - addNew() and selectOld() are private methods to
help us out - Making private methods for these very different
tasks simplifies things in onMousePress and makes
it more readable.
// prepare to to drag it around the screen.
public void onMousePress(Location point)
selected null // indicate nothing currently
selected if(selectOrAdd.getSelectedItem().equa
ls("Add new item")) addNew(point)
else selectOld(point)
12addNew()
- How this works
- Make sure there is more space in the array
- Figure out which color the user chose
- Figure out which shape the user chose
- Create a shape and add it at the end of the array
- Set its color
- Center it
- Increment the number of elements in the array by 1
// Add new geometric shape where clicked. Type
and color of // object is determined by the
settings of the color and // shape choice
buttons. private void addNew(Location point)
if (numObjects lt MAX_OBJECTS) // only add if
still room // local variable - color of
object Color objectColor Object
colorString colorChoice.getSelectedItem()
if (colorString.equals("Red"))
objectColor Color.red else if
(colorString.equals("Green"))
objectColor Color.green else
objectColor Color.blue //
string from shapeChoice selection Object
shapeString shapeChoice.getSelectedItem()
// create new object to be shape chosen
if (shapeString.equals("Square"))
geomObjectnumObjects new
FilledRect(point, 100, 100, canvas)
else geomObjectnumObjects
new FilledOval(point, 100, 100, canvas)
geomObjectnumObjects.setColor(obj
ectColor) geomObjectnumObjects.move(-50,
-50) // of object numObjects
numObjects 1
13addNew()
0
MAX_OBJECTS - 1
1
2
3
4
. . .
numObjects is 3
- Suppose there are 3 elements in the array, and we
add a red square. - We check to see if theres room
- Then, if there is, we add it at the end of our
shapes and increment numObjects.
14addNew()
0
MAX_OBJECTS - 1
1
2
3
4
. . .
numObjects is now 4
- Suppose there are 3 elements in the array, and we
add a red square. - We check to see if theres room
- Then, if there is, we add it at the end of our
shapes and increment numObjects
15selectOld()
- This routine finds the object we clicked on in
the array - This is called searching when we go through an
array or list to get a particular element - We test each shape to see if it containst the
point where the user clicked - If it does, we know the user clicked on it
- We then send that shape to the front
16selectOld()
private void selectOld(Coords point)
// see if point is in an object for (int
objNum 0 objNum lt numObjects objNum)
if (geomObjectobjNum.contains(point))
// remember top-most object
w/point selected
geomObjectobjNum
if (selected ! null) // if point is in one
of the objects lastPoint point
selected.sendToFront()
- The first for loop searches and tests each
element by calling contains() on it - If the element is found, then
- store it in the selected instance variable
- We also set lastPoint, in preparation for
dragging the object - selected remains null if the user didnt click
anything.
17Were done, right?
- Not quite. The program doesnt do quite what a
normal user might expect. - Youll notice that the shapes are initially
layered in the order they were created - Some are on top of others
- When we click, we really want to pick the topmost
shape under the mouse, but our program doesnt do
that - It picks the shape under the mouse that was last
created, and sends it to the front - Most users expect that when they click, theyre
clicking on what they see
Clicking here could select the blue square!
18Layering
- Solution here is to store objects in order of
their layering - Whenever we send something to the front, we need
to also move it to the end of our array. - If we send the blue square to the front, we move
it to the end, and shift all subsequent elements
left
19New version of selectOld()
private void selectOld(Coords point)
// see if point is in an object int
selectIndex 0 for (int objNum 0
objNum lt numObjects objNum) if
(geomObjectobjNum.contains(point))
// remember top-most object w/point
selected geomObjectobjNum
selectIndex objNum
if (selected ! null) // if point is
in one of the objects lastPoint
point selected.sendToFront()
for (int objNum selectIndex objNum lt
numObjects-1 objNum)
geomObjectobjNum geomObjectobjNum1
geomObjectnumObjects-1
selected
- We now store the index of the frontmost item the
user clicked on - We also insert a loop to do the shifting of
elements
20New version of selectOld()
- Take a look at that new loop
- What if I wrote it like this
- This is broken. Why? What happens to our array?
for (int objNum selectIndex objNum lt
numObjects-1 objNum)
geomObjectobjNum geomObjectobjNum1
geomObjectnumObjects-1 selected
for (int objNum numObjects objNum gt
selectIndex objNum--)
geomObjectobjNum-1 geomObjectobjNum
geomObjectnumObjects-1 selected
21Searching
- We used a loop to search for an object in an
array - This loop finds the last object in the array that
contains the point - Stores the object in selected
- Stores its index in selectIndex
- This code is not as clean as it could be!
int selectIndex 0 for (int objNum 0
objNum lt numObjects objNum) if
(geomObjectobjNum.contains(point))
// remember top-most object w/point
selected geomObjectobjNum
selectIndex objNum
22Searching
int selectIndex 0 for (int objNum 0
objNum lt numObjects objNum) if
(geomObjectobjNum.contains(point))
// remember top-most object w/point
selected geomObjectobjNum
selectIndex objNum
- We could make this better by starting at the
right end of the list and finding the first
object that contains the point - Wouldnt have to go through the whole list that
way - We also dont really need that extra variable for
selectIndex - Could use the loop variable, objNum, for the same
thing
23Better Search
int objNum numObjects - 1 while
(objNum gt 0 !geomObjectobjNum.contains(point
)) objNum-- if (objNum gt 0)
//if we found something
selected geomObjectobjNum //set
selected
- This loop will stop once it finds the topmost
object that contains the point - Doesnt have to go through all the objects all
the time - objNum is positive at the end if we found
something - Its the index of the object to select!
- Its -1 if we went through all the objects and
didnt find anything - We set selected only if objNum is nonnegative