Monday, August 11, 2008

Simple Mouse Interaction in Java

Building on the basic graphics we've done in Very Basic Java Graphics--3 Examples and A Most Basic Graphics App we'll be adding mouse interaction in this example.

/* MousePanel.java

This program adds the ability to respond to
mouse events to the BasicPanel program.

The mouse clicks are used to draw on the
panel area using drawline instructions.

mag-30Apr2008
*/

// Import the basic necessary classes.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class MousePanel extends JPanel implements MouseListener{

public MousePanel(){
super();
pointX=20;
pointY=20;
oldX=0;
oldY=0;
addMouseListener(this);
}

int pointX, pointY, oldX, oldY;

public void paintComponent(Graphics g){
// Draw a line from the prior mouse click to new one.
g.drawLine(oldX,oldY,pointX,pointY);
}

public void mouseClicked(MouseEvent mouse){
// Copy the last clicked location into the 'old' variables.
oldX=pointX;
oldY=pointY;
// Get the location of the current mouse click.
pointX = mouse.getX();
pointY = mouse.getY();
// Tell the panel that we need to redraw things.
repaint();
}

/* The following methods have to be here to comply
with the MouseListener interface, but we don't
use them, so their code blocks are empty. */
public void mouseEntered(MouseEvent mouse){ }
public void mouseExited(MouseEvent mouse){ }
public void mousePressed(MouseEvent mouse){ }
public void mouseReleased(MouseEvent mouse){ }

public static void main(String arg[]){
JFrame frame = new JFrame("MousePanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(250,250);

MousePanel panel = new MousePanel();
frame.setContentPane(panel);
frame.setVisible(true);
}
}

To add mouse interaction, we're taking advantage of an interface from the java.awt.events package called MouseListener. When we implement MouseListener as part of our JPanel class, then call addMouseListener(this) as part of our MousePanel() constructor, our program is "wired up" to the mouse, so that our MousePanel gets mouse events from the JVM.

Implementing the MouseListener interface requires that we implement all the methods called for by the interface. We only use MouseClicked() in this example, however, so it's the only one that has code in its code block.

This program lets you draw by clicking the mouse at various places in the MousePanel's drawing area, drawing a line from the prior click location (or from top left for the first click) to the location of the current click.

Here's a little challenge for you:

Change the program so that it doesn't draw a line from upper left on the first click, but instead draws a dot in the location of the first click. Later clicks will then draw lines from the prior click's location.

Hint: If you set the initial oldX and oldY values to a value that isn't in the visible MousePanel area, you can tell if there haven't been any prior clicks.
StumbleUpon

Friday, August 8, 2008

Reference Types: Names and Objects

When we learned about primitive variables we learned that they are a way of storing a simple value, like a number or a true-false state. We give them a name, and whenever we want to get that value we use that name. Whenever we want to change the value that's stored, we set the name equal to the new value:
int value;     //Declare an integer variable named value.
value=100; // Store the number 100 in value.
System.out.println(value); // Print the number in value, "100"
value=20; // Put 20 in value. Over-writes the 100.
count=value; // Gets the number from value and puts
// it in count.
// Assumes 'count' was declared as an int before.

When we use objects, we're using a more complex kind of variable. We don't do it for the sake of complexity, but because adding some complexity here makes things a lot simpler elsewhere in our program. A lot simpler.

Object variables are called "reference types", the type is actually the class that the object belongs to. The difference between a reference variable and a primitive variable is that a primitive variable actually is a storage location in computer memory that holds the stored information. A reference variable is a name that names a specific type of information. It doesn't actually hold the information, it's just associated with an object that actually holds the information.

This why there's a two step process in creating a Java variable. The first step, declaration, sets up a name we're going to use for a particular type of object. The second step, initialization, associates that name with an object--creating a new object if necessary.

Let's say I'm talking to a friend. I say, "I'm going to get a hamster and call it Wilmot."

"That's nice," says the friend. "Can I see Wilmot?"

"I don't have him yet."

"What color is Wilmot?"

"I don't know, I don't have a hamster yet."

Then I go to the pet store and pick up a hamster. I call him Wilmot, put him in a cage and take him home. I've now initialized the name Wilmot I declared to my friend earlier to point to a specific hamster.

Now when my friend says "Can I see Wilmot?" I can show him a hamster, and say "This is Wilmot." When he wants to know the color, there is an object to get the color of.

In Java terms, if I had a Hamster class, I could declare a name like this:
Hamster wilmot;

I now have a name for a Hamster object, but no Hamster. I can initialize the reference variable by getting a new Hamster object using the class's constructor, Hamster():
wilmot=new Hamster();

Now I have a Hamster object associated with the name. The name references the Hamster object that's been created. Hence the term "reference variable".

Now, if I create a new name and make it point to the same Hamster object, it becomes a new name for the same object:
Hamster fluffy;
fluffy=wilmot;

Now, if I make any changes to fluffy they also happen to wilmot. For example, if wilmot's size is 10cm, and I set fluffy's size to 12cm, then get wilmot's size it will be 12cm.

This is different from what happens with primitive variables. If I do the same thing with a pair of primitive variables like this:
int value, count;
value=100; // Initialize value to 100;
count=value; // Set count equal to value.
count=count-20; // Subtract 20 from count.
// We could have said 'count-=20;', too.
System.out.println("value= " + value); // Print value.
System.out.println("count= " + count); // Print count.

Then the output will be:
value= 100
count= 80

With a primitive variable, when we set it equal to another primitive we get a copy of the value in that primitive's own storage. When we set a reference variable equal to another reference variable, we are now referring to the same object as the other reference variable. In pet terms, it's like giving our hamster a second name. We might call it wilmot or fluffy, but they're both the same hamster.

If we need to have each name apply to a different hamster, we need to go back to the pet store for another hamster. In Java, we need to use the constructor to get another Hamster object:
Hamster wilmot, fluffy;
wilmot=new Hamster();
fluffy=wilmot; // fluffy and wilmot are now both names
// for the same Hamster object. Anything we do to fluffy
// will also apply to wilmot, and vice versa.
fluffy=new Hamster();
// Now fluffy applies to a different Hamster object.
// We can make changes to fluffy and
// they won't affect wilmot. We now have two
// Hamster objects, each with its own name
// to refer to it.

But what if we want it to act like a primitive object? What if we want a copy of wilmot to make changes to without affecting wilmot? Then we use a method of the object's class to create a new object that's a copy of that object. Usually this will be clone():
Hamster wilmot, fluffy;
wilmot=new Hamster();
fluffy=wilmot.clone();

Now fluffy is a copy of wilmot, and we can make changes to fluffy without affecting wilmot. Note: whether a class has the clone() method varies from class to class. Normally, if the class implements the Clonable interface then it has a clone() method that works this way.
StumbleUpon

Monday, August 4, 2008

Mini-Review: Beginning Programming with Java for Dummies by Barry Burd

Of the books currently available, this one is my favorite for teaching non-programmers the basics of programming. This is in spite of the fact that it goes against a few strongly-held opinions of mine. I have worked through the book myself, and had a student with no prior programming experience use the book for self-study. So the opinions here are based on my own experience as an instructor and the feedback I've gotten from the student.

The writing style of this book is fun and easy to read. This is always a big plus for books that teach a complex and unfamiliar subject. The material is also varied from chapter to chapter, meaning that you won't be going to sleep writing different kinds of loops for three straight chapters. Subjects are interleaved, for example, there is a section on using files that breaks up material on loops and iteration.

The start of the book is quite leisurely. This is valuable in a book for non-programmers, I feel. The pace of the book picks up as it goes, so don't be fooled into thinking the book is just a brief tutorial that's been padded out into book length. The early sections are also quick reads, and sections on installing Java can be scanned or skipped over as appropriate. The pages dedicated to installing the JDK are there for a good reason, though. My experience is that just getting the JDK installed and running is one of the biggest hurdles for non-programmers who want to learn Java.

The differences I have with this book are few, but significant. The first is that graphics are left until the very tail end of the book. As I've stated elsewhere, I'm a proponent of teaching graphics early. I feel they're a good motivator for new programmers, and they allow new programmers to visualize the effects of their program's flow control structures in a way that rows of numbers can't equal.

The second difference I have with this book's approach is the use of an integrated development environment (IDE) right from the start. I've also commented in a prior article why I think it's a good idea to at least be familiar with common command line operations before starting with the IDE. I feel that starting with an IDE right off glosses over some skills that are crucial to programmers at any skill level.

The third concern I have with the book is that it recommends the use of a Windows-only IDE for use with the book. Now, if this were a .Net book or something similarly tied to a single platform I wouldn't have any problem with this. But this is a Java book! Why not a good multiplatform IDE written in Java? It's not like there aren't any good choices. My student was working on a Mac, and was able to complete the work in the book with no problem using, primarily, Arachnophilia but also using BlueJ for the latter part of the book.

I would also be concerned that people seeing the recommendation of a platform-specific IDE early in the book would think that therefore the book itself contains a substantial measure of platform-specific content. It doesn't, but flipping through the start of the book isn't enough to make that clear.

The focus of the book is on the basics of programming. It does not dip heavily into object oriented programming. It simply uses Java and its facilities to teach introductory programming in much the same way as one might use C or Pascal for the same purpose. I don't yet consider this a problem, though Greenfoot may convince me that objects and classes should be right up front now. However, I feel that starting with this book and then moving on to other resources like Greenfoot and Head First Java to develop a better understanding of Java and object oriented programming is a perfectly acceptable way to learn.

Even with its problems, I consider this book to be the best on the market for a non-programmer. It does not go as deeply into Java as Beginning Programming in Java for the Absolute Beginner, but it's an easier read and overall I like the structure better even though it covers less.

Final Grade: 90%, A

Pros:
Easy to read.
Good pacing of material.
Doesn't get boring.
A very good introduction to programming.

Cons:
Uses an IDE, and recommends a Windows-specific IDE (though any multiplatform IDE will work.)
Graphics are left until the very end.
Limited scope, but it's easy to go on from here.

Recommendation:
Get it if you're a non-programmer looking to learn how to program. You may also want to get the "next" Java book you plan on using at the same time, and start referring to it as you work through this one. You should consider downloading Greenfoot then going through its tutorials to get a grounding in classes and objects. You'll also want to get a multi-platform IDE for Java, even if you are on Windows. You may decide to use Greenfoot for this, or BlueJ or Arachnophilia (or perhaps even Eclipse or NetBeans, if you have a mentor to help you get started with them.)
StumbleUpon

Saturday, August 2, 2008

Creating a Java Variable: Two Steps

There are two steps to creating a variable; declaration and initialization.

Declaration is creating a name and saying what type of variable it names:
int count;
String name;
Scanner input;
JFrame frame;

Here we're saying "I hereby declare that I have a variable named count and that it will be used to name an integer variable. I also declare that a variable called name will be used to refer to a String object." And so on.

Now, these variables are only half done at this point. We've created names, but we haven't actually associated them with anything yet. It's like telling someone the names of your pets before you actually get them.

"I have a hamster named Wilmot and a cat called Tiger and a dog named Bowser."

"Where are they?"

"I don't have them yet."

At this point, telling someone to feed Wilmot wouldn't make much sense. You need a pet to go with the name. Similarly, asking your program to fetch data from your Scanner named input doesn't make sense until you have attached it to an actual instance of a Scanner. So let's do it:
input=new Scanner(System.in);

This is called initialization. We gave it an initial value. In this case, we created a new Scanner object and made input refer to it (using the = sign.)

We can initialize the rest, too:
count=0;
name="";
frame=new JFrame("Hello.");

We initialized count to 0, name to an empty string, and frame to a new Jframe object.

Now we have things associated with the names. Now if we tell our program to get data from input and set name to point to it, it'll be able to do so, because now there's an actual Scanner connected with the name input:
name=input.next();


Shortcut:Two Steps in One

You can declare and initialize a variable in one statement. But you still have to do both.*
int count=0;
String name="";
Scanner input=new Scanner(System.in);
JFrame frame=new JFrame("Hello.");

This looks confusing. It's the redundancy of seeing, for example, Scanner twice on the same line. This happens because the object name, Scanner, is the same as the constructor name for making a new object of that type, Scanner(), except that the constructor has parentheses after it (marking it as a method, and the capitalized name being the name of a class tells you that it's a constructor method that makes a new one of those objects.)

We don't have to create a new object for initialization. If there's already an object of that type available, we can initialize a newly declared variable to that same object:
Scanner keyboard=input;

This declares a new Scanner called keyboard and initializes it to point to the same Scanner as input. In pet terms, this is like giving a nickname to your hamster Wilmot. You may have two names, say, Wilmot and Fluffy, but you've still got one hamster--he just goes by either name.
Hamster wilmot=new Hamster("Syrian", AGOUTI);
Hamster fluffy=wilmot;

If you want another object, you need to create one:
Hamster fred=new Hamster("Teddy Bear", BANDED);
Now you have a second hamster called fred.

Further reading.


*Actually, Java doesn't strictly require initialization all the time. But it's good programming practice to do so. It prevents a lot of bugs and nasty surprises in your programs.
StumbleUpon