PDA

View Full Version : [Java] Add a MouseListener to Java Image?



MetKiller Joe
April 10th, 2009, 09:09 AM
http://img2.imageshack.us/img2/1876/littlephysicsapp.jpg

I have the area where you see those dots double-buffered. Is there anyway I can get that area to respond to mouse events? I did try to add the .addMouseListener to the image and graphics object, nothing. I tried listening to the area on the applet below the image, nothing. This is in awt.

Code:



package bouncy;

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Arrays;
public class Bouncy extends Applet implements MouseListener, MouseMotionListener{

Button newAtom;
Button reset;
Button Awesome;
boolean awesome = false;
int n = 0;
Button DragBox;
boolean dragBox = false;

TextField pxSecX;
TextField pxSecY;
TextField pxSec2X;
TextField pxSec2Y;
TextField size;

Checkbox xVector = new Checkbox("X Vector", true);
Checkbox yVector = new Checkbox("Y Vector", true);
Checkbox summedVector = new Checkbox("Summed Vector", true);
Checkbox Coordinates = new Checkbox("Coordinates", true);


Image backBuffer;
Graphics drawBuffer;

Atom[] atom;
int bW = 500;
int bH = 500;
int mX, mY;

int xAnchor = 10;
boolean boolX;
int yAnchor = 10;
boolean boolY;
int sumAnchor = (int)Math.sqrt(Math.pow(xAnchor, 2) + Math.pow(yAnchor, 2));
boolean boolSum;
int radius;
int radiusAnchor;

double velocity;
double accel;
boolean outBox = false;
boolean animate = false;

Point box = new Point(225, 10);

@Override
public void init() {
this.setSize(800, 600);

atom = new Atom[0];
backBuffer = createImage(bW - 1, bH - 1);
drawBuffer = backBuffer.getGraphics();



newAtom = new Button();
reset = new Button();
Awesome = new Button();
DragBox = new Button();


pxSecX = new TextField();
pxSecY = new TextField();

pxSec2X = new TextField();
pxSec2Y = new TextField();

size = new TextField();
add(newAtom);
newAtom.addMouseListener(this);

add(reset);
reset.addMouseListener(this);

add(DragBox);
DragBox.addMouseListener(this);
DragBox.addMouseMotionListener(this);

add(Awesome);
Awesome.addMouseListener(this);

add(pxSecX);
pxSecX.addMouseListener(this);

add(pxSecY);
pxSecY.addMouseListener(this);

add(pxSec2X);
pxSec2X.addMouseListener(this);

add(pxSec2Y);
pxSec2Y.addMouseListener(this);

add(size);
size.addMouseListener(this);

add(xVector);
xVector.addMouseListener(this);

add(yVector);
yVector.addMouseListener(this);

add(summedVector);
summedVector.addMouseListener(this);

add(Coordinates);
Coordinates.addMouseListener(this);

this.addMouseListener(this);
repaint();


}
@Override
public void update(Graphics g){
paint(g);
}

@Override
public void paint(Graphics g){
newAtom.setLocation(10, 10);
newAtom.setSize(65, 25);
newAtom.setLabel("Spawn");

reset.setLocation(10, 35);
reset.setSize(65, 25);
reset.setLabel("Reset");

Awesome.setLocation(10, 350);
Awesome.setSize(65, 25);
Awesome.setLabel("Awesome");

DragBox.setLocation(new Point((int)(box.getX() - 65), (int)box.getY()));
DragBox.setSize(65, 25);
DragBox.setLabel("Drag Box");
DragBox.hide();
DragBox.disable();

g.drawString("px/s (X)", 80, 75);
g.drawString("px/s (Y)", 80, 100);

g.drawString("px/s^2 (X)", 80, 125);
g.drawString("px/s^2 (Y)", 80, 150);

g.drawString("Radius", 80, 175);

pxSecX.setLocation(10, 60);
pxSecX.setSize(65, 25);

pxSecY.setLocation(10, 85);
pxSecY.setSize(65, 25);

pxSec2X.setLocation(10, 110);
pxSec2X.setSize(65, 25);

pxSec2Y.setLocation(10, 135);
pxSec2Y.setSize(65, 25);

size.setLocation(10, 160);
size.setSize(65, 25);

xVector.setLocation(10, 185);
yVector.setLocation(10, 210);
summedVector.setLocation(10, 235);
Coordinates.setLocation(10, 260);

if(dragBox) g.clearRect(185, 10, this.getWidth() - 185, this.getHeight() - 10);
g.drawRect((int)(box.getX()), (int)(box.getY()), bW, bH);
if(animate){
for(int frames = 0; frames < 200; frames++){
animation();
try
{Thread.sleep(16);}
catch(Exception e)
{System.err.println(e.getMessage());}
if(dragBox) g.clearRect(185, 10, this.getWidth() - 185, this.getHeight() - 10);
g.drawImage(backBuffer,(int)(box.getX() + 1), (int)(box.getY() + 1), this);
if(!awesome) drawBuffer.clearRect(0, 0, backBuffer.getWidth(this), backBuffer.getHeight(this));
}
}
}
public void animation() {
for(int atoms = 0; atoms < atom.length; atoms++){
drawBuffer.fillOval((int)atom[atoms].realX(), (int)atom[atoms].realY(), (int)atom[atoms].getSize(), (int)atom[atoms].getSize());
if(!awesome && Coordinates.getState()){
drawBuffer.drawString("X: " + (int)atom[atoms].getX(), (int)atom[atoms].getX() + (int)atom[atoms].getSize() + 1, (int)atom[atoms].getY());
drawBuffer.drawString("Y: " + (int)atom[atoms].getY(), (int)atom[atoms].getX() + (int)atom[atoms].getSize() + 1, (int)atom[atoms].getY() + 10);
}
//sum of velocity vectors
if(summedVector.getState()){
drawBuffer.setColor(Color.RED);
drawBuffer.drawLine((int)atom[atoms].getX(), (int)atom[atoms].getY(),
(int)(atom[atoms].getX() + atom[atoms].getXSpeed()),
(int)(atom[atoms].getY() + atom[atoms].getYSpeed()));
}
if(xVector.getState()){
//X vector
drawBuffer.setColor(Color.GREEN);
drawBuffer.drawLine((int)atom[atoms].getX(), (int)atom[atoms].getY(),
(int)(atom[atoms].getX() + atom[atoms].getXSpeed()),
(int)(atom[atoms].getY()));
}
if(yVector.getState()){
//Y vector
drawBuffer.setColor(Color.BLUE);
drawBuffer.drawLine((int)atom[atoms].getX(), (int)atom[atoms].getY(),
(int)atom[atoms].getX(),
(int)(atom[atoms].getY() + atom[atoms].getYSpeed()));
}
drawBuffer.setColor(Color.BLACK);
atom[atoms].detectCollision(atom);
atom[atoms].xAccel();
atom[atoms].yAccel();

atom[atoms].xMove();
atom[atoms].yMove();
}
}
public void mouseMoved(MouseEvent m){
}
public void mousePressed(MouseEvent m){
if(m.getSource() == newAtom){
animate = true;
if(!((pxSecX.getText().equals("") && pxSecY.getText().equals("")) &&
(pxSec2X.getText().equals("") && pxSec2Y.getText().equals("")) &&
(size.getText().equals("")))){
ArrayList al = new ArrayList(Arrays.asList(atom));
al.add(new Atom(new Point(150, 150),
Double.parseDouble(size.getText()),
Double.parseDouble(pxSecX.getText()),
Double.parseDouble(pxSecY.getText()),
Double.parseDouble(pxSec2X.getText()),
Double.parseDouble(pxSec2Y.getText()),
(int)(box.getX() + 1), (int)(box.getY() + 1), bW - 1, bH - 1));
atom = (Atom[])al.toArray(new Atom[al.size()]);
repaint();
}
}
if(m.getSource() == reset){
animate = true;
atom = new Atom[0];
drawBuffer.clearRect(0, 0, backBuffer.getWidth(this), backBuffer.getHeight(this));
repaint();
}
if(m.getSource() == Awesome){
if(!awesome){
awesome = true;
n++;
}
if(awesome && n != 1) awesome = false;
n = 0;
System.out.println(awesome);
}
if(m.getSource() == DragBox){
mX = m.getX();
mY = m.getY();
dragBox = true;
}
}
public void mouseDragged(MouseEvent m){
if(m.getSource() == DragBox && dragBox){
box.setLocation((int)(box.getX() + (m.getX() - mX)), (int)(box.getY() + (m.getY() - mY)));
mX = m.getX();
mY = m.getY();
repaint();
}
}
public void mouseReleased(MouseEvent m){
if(dragBox) dragBox = false;
}
public void mouseClicked(MouseEvent m){

}
public void mouseExited(MouseEvent m){

}
public void mouseEntered(MouseEvent m){

}
}

flibitijibibo
April 10th, 2009, 09:26 AM
There isn't a way that I know of to add it to a specific image. What you can do, however, is create a set of coordinates for the image's dimensions (int x1, x2, y1, y2; for example), and use the mouseClick/Move/Drag methods to check if it's within those given coordinates. It would look like this:

if ((m.getX() > x1 && m.getX() < x2) && (m.getY() > y1 && m.getY() < y2)){
blahdiblahdiblah;
and so on;
}

Phopojijo
April 10th, 2009, 02:55 PM
Here's a program that I wrote that uses this. Note -- when I used the Netbeans visual editor I had serious problems... so I programmed the interface by hand.

The assignment's long since handed in and is not actually what you're doing. It'll give you an example of how to do it though.

Note: The program functioned by creating a class "Paints" that extended JPanel... and I used the mouse listener to determine what's going on with the JPanel... and painted the BufferedImage on the JPanel.

ComplexNumber.java

/*
* A class to be used with the Mandelbrot program for assignment 5.
* by Alan McLeod
*/
public class ComplexNumber {

private double re;
private double im;

public ComplexNumber() {
re = 0;
im = 0;
}

public ComplexNumber(double a) {
re = a;
im = 0;
}

public ComplexNumber(double a, double b) {
re = a;
im = b;
}

public double getReal() {
return re;
}

public double getIm() {
return im;
}

public ComplexNumber add(ComplexNumber z) {
double x, y;
x = re + z.re;
y = im + z.im;
return new ComplexNumber(x, y);
}

public ComplexNumber subtract(ComplexNumber z) {
double x, y;
x = re - z.re;
y = im - z.im;
return new ComplexNumber(x, y);
}

public ComplexNumber multiply(ComplexNumber z) {
double x, y;
x = re * z.re - im * z.im;
y = re * z.im + im * z.re;
return new ComplexNumber(x, y);
}

public ComplexNumber divide(ComplexNumber z) throws NumberDivideException {
double x, y;
if (z.re == 0 && z.im == 0) {
throw new NumberDivideException("Attempt to divide by zero!");
}
x = (re * z.re + im * z.im) / (z.re * z.re + z.im * z.im);
y = (z.re * im - z.im * re) / (z.re * z.re + z.im * z.im);
return new ComplexNumber(x, y);
}

public double abs() {
return Math.sqrt(re * re + im * im);
}

public String toString() {
return re + " + " + im + "i";
}
} // end ComplexNumber class


NumberDivideException.java


public class NumberDivideException extends Exception {

public NumberDivideException() {
super("Illegal complex number operation!");
}

public NumberDivideException(String s) {
super(s);
}
} // end NumberDivideException


Fractal_GUI5c.java

/*
* Fractal Generator
* Keyboard Shortcuts:
* z -- Undo last view... because Ctrl+z messes with KeyListener.
* Spacebar -- Zoom Out
*/

/**
* Fractal Viewer generates fractals and outputs them on screen.
*
* @author Scott
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;


public class Fractal_GUI5c extends JFrame {

JPanel jPanel1;
Paints renderBuffer;
JButton jButton1;
JButton jButton2;
JLabel jLabel1;
BufferedImage topFrameBuffer = new BufferedImage(400,300,BufferedImage.TYPE_INT_RGB);

int column;
int row;
final static int MAX_ITERATIONS = 32; //Maximum number of iterations.
final static double ESCAPE_MODULUS = 2.0; //Maximum modulus.

final int height = 300;
final int width = 400;

//Declare all the variables required for positioning.
private double xMax = 2.26;
private double yMax = 2.26; //Initial BottomRight Corner
private double xMin = -2.24;
private double yMin = -2.24; //Initial TopLeft Corner
private double xMaxBuffer = 2.26; //Buffer for Undo's.
private double yMaxBuffer = 2.26;
private double yMinBuffer = -2.24;
private double xMinBuffer = -2.24;
private double xScale;
private double yScale;
private double xPositMin;
private double yPositMin;
private double xPositMax;
private double yPositMax;

//Launch the Window.
public Fractal_GUI5c()
{
initialize();
}//end constructor

public void initialize()
{
//Declarations
jPanel1 = new JPanel();
renderBuffer = new Paints();
jButton1 = new JButton();
jButton2 = new JButton();
jLabel1 = new JLabel();

//Window Settings
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(400, 340);
setResizable(false);
setVisible(true);
setTitle("Loose Screw Fractal Viewer"); //Yes that's what all those LS's meant.
//It's a habit from all the other code I write.
//So that we can figure out who wrote it.

setLayout(new BorderLayout());

//Configure the Panels
jPanel1.setBackground(new Color(216,216,255));
jPanel1.setBorder(new javax.swing.border.LineBorder(new Color(0,0,0),2,true));
jPanel1.setPreferredSize(new Dimension(400,40));
jPanel1.setLayout(new FlowLayout());

renderBuffer.setBackground(Color.BLACK);//To show people that the component just needs refreshing.
//People tend to understand that Black = Buffering from Youtube and such.
//Ahhh Ergonomics.

//Add the Panels
this.add(jPanel1, BorderLayout.PAGE_END);
this.add(renderBuffer, BorderLayout.CENTER);

//Configure and add the buttons and labels.
jButton1.setText("Refresh");
jButton1.setToolTipText("Repaints fractal if error occurs.");
jPanel1.add(jButton1);

jLabel1.setText(" Click and Drag to Zoom Box ");
jPanel1.add(jLabel1);

jButton2.setText("Zoom Out");
jButton2.setToolTipText("Sets zoom level to maximum (Spacebar)");
jPanel1.add(jButton2);

//Button Functionality
renderBuffer.repaint();
jButton1.addActionListener(new ActionListener()
{
public void actionPerformed (ActionEvent e){
renderBuffer.repaint();
renderBuffer.requestFocus();
}

});//end Button Action

jButton2.addActionListener(new ActionListener()
{
public void actionPerformed (ActionEvent e){
yMinBuffer = yMin;
yMin = -2.24;
yMaxBuffer = yMax;
yMax = 2.26;
xMinBuffer = xMin;
xMin = -2.24;
xMaxBuffer = xMax;
xMax = 2.26;
renderBuffer.repaint();
renderBuffer.requestFocus();
}
});//end Button action

//Mouse Input Stuff
renderBuffer.addMouseListener(new MouseListener()
{
public void mouseClicked (MouseEvent e){}
public void mouseEntered (MouseEvent e){}
public void mouseExited (MouseEvent e){}
public void mousePressed (MouseEvent e)
{
yScale = (yMax - yMin) / height; //In case they get messed around in undoes.
xScale = (xMax - xMin) / width;
xPositMin = xMin + e.getX() * xScale;
yPositMin = yMax - e.getY() * yScale;
}//end mousePressed
public void mouseReleased (MouseEvent e)
{
xPositMax = xMin + e.getX() * xScale;
yPositMax = yMax - e.getY() * yScale;

xMinBuffer = xMin;
yMinBuffer = yMin;
xMaxBuffer = xMax;
yMaxBuffer = yMax;

xMin = xPositMin;
xMax = xPositMax;
yMin = yPositMax;
yMax = yPositMin;
renderBuffer.repaint();
}//end mouseReleased
});//end Mouse action

//Keyboard Input Stuff.
renderBuffer.setFocusable(true);
renderBuffer.addKeyListener(new KeyListener()
{
public void keyTyped(KeyEvent e)
{
if (e.getKeyChar() == 'z' || e.getKeyChar() == 'Z')
{
double xMinBuffer2 = xMinBuffer;
double yMinBuffer2 = yMinBuffer;
double yMaxBuffer2 = yMaxBuffer;
double xMaxBuffer2 = xMaxBuffer;
xMinBuffer = xMin;
xMaxBuffer = xMax;
yMinBuffer = yMin;
yMaxBuffer = yMax;
xMin = xMinBuffer2;
xMax = xMaxBuffer2;
yMax = yMaxBuffer2;
yMin = yMinBuffer2;
renderBuffer.repaint();
} //end Undo
if (e.getKeyChar() == ' ')
{
yMinBuffer = yMin;
yMin = -2.24;
yMaxBuffer = yMax;
yMax = 2.26;
xMinBuffer = xMin;
xMin = -2.24;
xMaxBuffer = xMax;
xMax = 2.26;
renderBuffer.repaint();
renderBuffer.requestFocus();
}//end ZoomOut

}//end keyTyped

public void keyPressed(KeyEvent e) {

}

public void keyReleased(KeyEvent e) {

}
});//end Keyboard

}//end initialize.

private class Mandelbrot
{
private int generateFractal(double xPosit, double yPosit)
{
ComplexNumber c = new ComplexNumber(xPosit, yPosit);
ComplexNumber z = new ComplexNumber(0,0);
Color toReturn = null;
int iterations = 0;
double modulus = 0;
boolean escaped = false;

while (iterations < MAX_ITERATIONS && !escaped)
{
z = z.multiply(z).add(c);
modulus = z.abs();
escaped = modulus > ESCAPE_MODULUS;
iterations++;
}//end While Loop

if (escaped)
{
toReturn = setEscapeColour(iterations);
}
else
{
toReturn = setColour(modulus);
}

return toReturn.getRGB();
}//end generateFractal

private Color setEscapeColour(int iterations)
{
float intensity = 1.0F - (float) iterations / MAX_ITERATIONS;
intensity = Math.max(intensity, 0.1F);

return new Color(intensity/3,intensity/4,intensity/3);
}//end setEscapeColour

private Color setColour(double modulus)
{
float factor = (float) (modulus/ ESCAPE_MODULUS);
float incr = (float)Math.log10(factor * .99);

float r = Math.min(Math.abs(7F * incr) * factor, 1.0F);
float b = Math.min(Math.abs(factor + incr), 1.0F);
float g = Math.min(Math.abs(5.0F * incr) * factor, 1.0F);

return new Color(r,g,b);

}//end setColour

public BufferedImage drawBackBuffer()
{
double yPos;
double xPos;
yScale = (yMax - yMin) / height;
xScale = (xMax - xMin) / width;

BufferedImage mainBackBuffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

for (row = 0; row < height; row++)
{
yPos = yMax - row * yScale;
for (column = 0; column < width; column++)
{
xPos = xMin + column * xScale;
mainBackBuffer.setRGB(column, row, generateFractal(xPos, yPos));
//System.out.println(xScale);
}//end for
}//end for

return mainBackBuffer;
}//end drawBackBuffer
}

private class Paints extends JPanel
{
public Paints()
{
super();
}

//Stuff for the Paints class here.
public void paint(Graphics g)
{
super.paint(g);

//topFrameBuffer.setRGB(40,40,Color.BLUE.getRGB());
g.drawImage(new Mandelbrot().drawBackBuffer(), 0, 0, rootPane);

}

}

//Launch the program.
public static void main(String[] args) {
new Fractal_GUI5c();
}

}

MetKiller Joe
April 10th, 2009, 06:42 PM
Thanks, I got it working. It was a lot simpler than I thought it was going to be to execute.

Also, my friend figured this out, and I can't bug him, but does anybody know how I would be able to create a thread and use it for each additional circle rendered? So, have each ball spawned in its own thread? I already have ArrayLists going.

MetKiller Joe
May 1st, 2009, 06:47 AM
http://img2.imageshack.us/img2/1876/littlephysicsapp.jpg

So, this project has progressed to the point where I felt that little animation window needed its own class. The problem is is there are buttons outlining the box which are also in the class along with a double-buffer.

I'd like to know it is possible/practical to have this class extending the Applet class and embed this class into the main applet? Or would it just be more practical to create it as a class and initialize all of the components inside the main applet; this would include the image for double-buffering (not bufferedimage).

I have tried extending the class as a component to be able to just initialize the image (createImage(width, height)) in a function within the class, but if that is executed within main, it returns a null pointer exception.

Any ideas? I'd like to keep all of the initialization contained within the class when I initialize the class itself to keep the code relatively clean. My main applet is already cluttered with interface code and other stuff.