|
Spring Semester 2003 |
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class One extends Applet implements MouseMotionListener {
public void init() {
addMouseMotionListener(this);
}
public void paint(Graphics g) { }
public void mouseMoved(MouseEvent e) {
int x = e.getX(), y = e.getY();
System.out.println("Mouse moved at: (" + x + ", " + y + ")");
}
public void mouseDragged(MouseEvent e) { }
}
that gets delivered from a simple HTML file
<html>
<head>
<title>All eyes on the mouse!</title>
</head>
<body>
<applet code=One.class height=300 width=300>
</applet>
</body>
</html>
This, of course, only watches the mouse. Let's add a visual indicator of where the mouse is.
This is our watching device:
import java.awt.*;
public class Device {
int x, y, r, R, targetX, targetY;
public Device(int x, int y, int r, int R) {
this.x = x;
this.y = y;
this.r = r;
this.R = R;
targetX = x + R;
targetY = y + R;
}
public void draw(Graphics g) {
g.drawOval(x, y, 2 * R, 2 * R);
g.fillOval(targetX - r, targetY - r, 2 * r, 2 * r);
}
}
Use this device in the applet, and it stares at you:
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class One extends Applet implements MouseMotionListener {
Device d = new Device(100, 100, 10, 30);
public void init() {
addMouseMotionListener(this);
}
public void paint(Graphics g) {
d.draw(g);
}
public void mouseMoved(MouseEvent e) {
int x = e.getX(), y = e.getY();
System.out.println("Mouse moved at: (" + x + ", " + y + ")");
}
public void mouseDragged(MouseEvent e) { }
}
Now let's pass info from the mouse listener to the device:
And since we know the device changes state we need to repaint.
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class One extends Applet implements MouseMotionListener {
Device d = new Device(100, 100, 10, 30);
public void init() {
addMouseMotionListener(this);
}
public void paint(Graphics g) {
d.draw(g);
}
public void mouseMoved(MouseEvent e) {
int x = e.getX(), y = e.getY();
// System.out.println("Mouse moved at: (" + x + ", " + y + ")");
d.targetX = x;
d.targetY = y;
repaint();
}
public void mouseDragged(MouseEvent e) { }
}
The device now monitors the mouse movement a little too closely. For the time being that's OK.
Let's draw the line that connects the center of the circle with the mouse pointer.
import java.awt.*;
public class Device {
int x, y, r, R, targetX, targetY;
public Device(int x, int y, int r, int R) {
this.x = x;
this.y = y;
this.r = r;
this.R = R;
targetX = x + R;
targetY = y + R;
}
public void draw(Graphics g) {
g.drawOval(x, y, 2 * R, 2 * R);
int xA = x + R, yA = y + R, xB = targetX, yB = targetY;
g.fillOval(targetX - r, targetY - r, 2 * r, 2 * r);
g.drawLine(xA, yA, xB, yB);
}
}
That looks like a rubber band. Can we identify the place where the border crosses the rubber band?
Let's place a second circle there.
import java.awt.*;
public class Device {
int x, y, r, R, targetX, targetY;
public Device(int x, int y, int r, int R) {
this.x = x;
this.y = y;
this.r = r;
this.R = R;
targetX = x + R;
targetY = y + R;
}
public void draw(Graphics g) {
g.drawOval(x, y, 2 * R, 2 * R);
int xA = x + R, yA = y + R, xB = targetX, yB = targetY;
g.fillOval(targetX - r, targetY - r, 2 * r, 2 * r);
g.drawLine(xA, yA, xB, yB);
double distance = Math.sqrt((xA - xB) * (xA - xB) +
(yA - yB) * (yA - yB));
double percent = R / distance;
int xC = (int) (percent * (xB - xA)) + xA;
int yC = (int) (percent * (yB - yA)) + yA;
g.fillOval(xC-4, yC-4, 8, 8);
}
}
The part in brown finds
the coordinates, (xC, yC) and
the part in blue draws
a small circle with a radius of 4 pixels centered in (xC, yC). Here's a picture that tries to make this even clearer:
Let's make a change:![]()
import java.awt.*;
public class Device {
int x, y, r, R, targetX, targetY;
public Device(int x, int y, int r, int R) {
this.x = x;
this.y = y;
this.r = r;
this.R = R;
targetX = x + R;
targetY = y + R;
}
public void draw(Graphics g) {
g.drawOval(x, y, 2 * R, 2 * R);
int xA = x + R, yA = y + R, xB = targetX, yB = targetY;
// g.fillOval(targetX - r, targetY - r, 2 * r, 2 * r);
g.drawLine(xA, yA, xB, yB);
double distance = Math.sqrt((xA - xB) * (xA - xB) +
(yA - yB) * (yA - yB));
double percent = R / distance;
int xC = (int) (percent * (xB - xA)) + xA;
int yC = (int) (percent * (yB - yA)) + yA;
g.fillOval(xC-r, yC-r, 2 * r, 2 * r);
}
}
That almost draws the small circle where needed. We need to bring it inside along the line by r.
import java.awt.*;
public class Device {
int x, y, r, R, targetX, targetY;
public Device(int x, int y, int r, int R) {
this.x = x;
this.y = y;
this.r = r;
this.R = R;
targetX = x + R;
targetY = y + R;
}
public void draw(Graphics g) {
g.drawOval(x, y, 2 * R, 2 * R);
int xA = x + R, yA = y + R, xB = targetX, yB = targetY;
// g.fillOval(targetX - r, targetY - r, 2 * r, 2 * r);
g.drawLine(xA, yA, xB, yB);
double distance = Math.sqrt((xA - xB) * (xA - xB) +
(yA - yB) * (yA - yB));
double percent = (R - r)/ distance;
int xC = (int) (percent * (xB - xA)) + xA;
int yC = (int) (percent * (yB - yA)) + yA;
g.fillOval(xC-r, yC-r, 2 * r, 2 * r);
}
}
And we can give up on the rubber band:
import java.awt.*;
public class Device {
int x, y, r, R, targetX, targetY;
public Device(int x, int y, int r, int R) {
this.x = x;
this.y = y;
this.r = r;
this.R = R;
targetX = x + R;
targetY = y + R;
}
public void draw(Graphics g) {
g.drawOval(x, y, 2 * R, 2 * R);
int xA = x + R, yA = y + R, xB = targetX, yB = targetY;
// g.fillOval(targetX - r, targetY - r, 2 * r, 2 * r);
// g.drawLine(xA, yA, xB, yB);
double distance = Math.sqrt((xA - xB) * (xA - xB) +
(yA - yB) * (yA - yB));
double percent = (R - r)/ distance;
int xC = (int) (percent * (xB - xA)) + xA;
int yC = (int) (percent * (yB - yA)) + yA;
g.fillOval(xC-r, yC-r, 2 * r, 2 * r);
}
}
But if we are inside the larger circle we need to be on the mouse.
import java.awt.*;
public class Device {
int x, y, r, R, targetX, targetY;
public Device(int x, int y, int r, int R) {
this.x = x;
this.y = y;
this.r = r;
this.R = R;
targetX = x + R;
targetY = y + R;
}
public void draw(Graphics g) {
g.drawOval(x, y, 2 * R, 2 * R);
int xA = x + R, yA = y + R, xB = targetX, yB = targetY;
// g.fillOval(targetX - r, targetY - r, 2 * r, 2 * r);
// g.drawLine(xA, yA, xB, yB);
double distance = Math.sqrt((xA - xB) * (xA - xB) +
(yA - yB) * (yA - yB));
int xC, yC;
if (distance < R - r) {
xC = targetX; yC = targetY;
} else {
double percent = (R - r)/ distance;
xC = (int) (percent * (xB - xA)) + xA;
yC = (int) (percent * (yB - yA)) + yA;
}
g.fillOval(xC-r, yC-r, 2 * r, 2 * r);
}
}
Now all you have to do is use as many devices as needed:
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class One extends Applet implements MouseMotionListener {
Device d1 = new Device( 50, 50, 10, 30),
d2 = new Device(100, 100, 10, 30),
d3 = new Device(150, 150, 10, 30),
d4 = new Device(200, 200, 10, 30);
public void init() {
addMouseMotionListener(this);
}
public void paint(Graphics g) {
d1.draw(g);
d2.draw(g);
d3.draw(g);
d4.draw(g);
}
public void mouseMoved(MouseEvent e) {
int x = e.getX(), y = e.getY();
// System.out.println("Mouse moved at: (" + x + ", " + y + ")");
d1.targetX = x; d1.targetY = y;
d2.targetX = x; d2.targetY = y;
d3.targetX = x; d3.targetY = y;
d4.targetX = x; d4.targetY = y;
repaint();
}
public void mouseDragged(MouseEvent e) { }
}
And things are easier to follow if we reactivate the rubber band:
import java.awt.*;
public class Device {
int x, y, r, R, targetX, targetY;
public Device(int x, int y, int r, int R) {
this.x = x;
this.y = y;
this.r = r;
this.R = R;
targetX = x + R;
targetY = y + R;
}
public void draw(Graphics g) {
g.drawOval(x, y, 2 * R, 2 * R);
int xA = x + R, yA = y + R, xB = targetX, yB = targetY;
// g.fillOval(targetX - r, targetY - r, 2 * r, 2 * r);
g.drawLine(xA, yA, xB, yB);
double distance = Math.sqrt((xA - xB) * (xA - xB) +
(yA - yB) * (yA - yB));
int xC, yC;
if (distance < R - r) {
xC = targetX; yC = targetY;
} else {
double percent = (R - r)/ distance;
xC = (int) (percent * (xB - xA)) + xA;
yC = (int) (percent * (yB - yA)) + yA;
}
g.fillOval(xC-r, yC-r, 2 * r, 2 * r);
}
}
And this is a test of what we have developed.