MouseDragged &Multi graphs

Hi,

I'm making a graphing calculator and just about to finish and i want to enhance it a little bit. I'm trying to add a MouseMotionListener so that you can drag the graph plotted on the panel/component.

the method I was thinking is that calculate the shift from the point where you start dragging to the point you release the mouse. and then repaint the graph based on that amount of shift.

//PSEUDO Code

publicvoid MouseDragged(MouseEvent e){

xi=e.getX();

yi=e.getY();//init coordinates: where the dragging starts

xf=e.getX();

yf=e.getY();//final coordinates: where the dragging stops(mouse released)

repaint(orignal graph+shift);

}

But i don't know how to accomplish this. how to get the initial and final coordinates? what is the MouseEvent e passed here?

Thanks!

Typo

Message was edited by:

andy_tok

[1117 byte] By [andy_toka] at [2007-11-26 15:53:36]
# 1

simple demo

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

class Testing

{

public void buildGUI()

{

Dragger d = new Dragger();

JPanel panel = new JPanel(null);

JButton btn = new JButton("OK");

btn.addMouseListener(d);

btn.addMouseMotionListener(d);

btn.setBounds(100,100,75,25);

panel.add(btn);

JLabel lbl = new JLabel("Hello World");

lbl.addMouseListener(d);

lbl.addMouseMotionListener(d);

lbl.setBounds(200,100,75,25);

panel.add(lbl);

JFrame f = new JFrame();

f.getContentPane().add(panel);

f.setSize(600,400);

f.setLocationRelativeTo(null);

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f.setVisible(true);

}

public static void main(String[] args)

{

SwingUtilities.invokeLater(new Runnable(){

public void run(){

new Testing().buildGUI();

}

});

}

}

class Dragger extends MouseAdapter implements MouseMotionListener

{

Point startPt;

JComponent comp;

public void mouseMoved(MouseEvent me){}

public void mouseDragged(MouseEvent me)

{

comp.setLocation(comp.getX()+me.getX()-startPt.x,comp.getY()+me.getY()-startPt.y);

}

public void mousePressed(MouseEvent me)

{

startPt = me.getPoint();

comp = (JComponent)me.getSource();

}

}

Michael_Dunna at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 2

Thanks!

But in my case, the graph is drawed on a JComponent, and what I want to drag is actually the graph. I'm thinking about creating kind of window and put it on top of the graph JComponent which is made larger than the window on purpose, so that only the part of the graph JComponent inside the window would be displyed. In this way, i can drag the graph JComponent without leaving any empty space on the main JFrame.

But that's just my idea and I don't know if that's feasible. If anyone can give some suggestions, that'll be great!

Message was edited by:

andy_tok

andy_toka at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 3

> Thanks!

> But in my case,

you asked this

> how to get the initial and final coordinates?

I posted a working example so you could see it in operation, instead of just this bit

comp.setLocation(comp.getX()+me.getX()-startPt.x,comp.getY()+me.getY()-startPt.y);

if you are drawing a graph it must start at an x,y so the principle would be the same,

instead of setLocation(), which calls repaint(), you would recalcualte x and y,

as above, then call repaint(), for your paintComponent() to redraw the graph

Michael_Dunna at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 4

Thanks! I tried that actually.

Here is a simplified version of my code, with only the x,y axis displayed. I had problems get it worked. The graph can be dragged well in the horizontal direction but kinda weird in the vertical direction.

DrawG is the graph JComponent

import java.awt.*;

import javax.swing.*;

import java.util.*;

import java.awt.event.*;

public class Graph extends JFrame implements ActionListener, MouseListener, MouseMotionListener

{

JTextField fx = new JTextField (20);

JButton gf = new JButton ("GRAPH");

DrawG dg;

JPanel fun = new JPanel ();

public Graph ()

{

super ("Graph");

setSize (500, 600);

setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

dg = new DrawG ();

dg.addMouseListener (this);

dg.addMouseMotionListener (this);

gf.addActionListener (this);

fun.setLayout (new BorderLayout ());

fun.add (gf, BorderLayout.EAST);

fun.add (fx, BorderLayout.WEST);

getContentPane ().setLayout (new BorderLayout ());

getContentPane ().add (dg, BorderLayout.CENTER);

getContentPane ().add (fun, BorderLayout.SOUTH);

setVisible (true);

}

public void actionPerformed (ActionEvent e)

{

/**if (e.getSource () == gf)

{

dg.setExpression (fx.getText ());

}**/

}

Point startPt;

public void mouseMoved (MouseEvent me)

{

}

public void mouseDragged (MouseEvent me)

{

//System.out.println("start "+startPt.x+" "+startPt.y);

//System.out.println("end "+me.getX()+" "+me.getY());

dg.setXmin (-10 + DrawG.convertX (-me.getX () + startPt.x));

dg.setXmax (10 - DrawG.convertX (me.getX () + startPt.x));

dg.setYmin (-10 + DrawG.convertY (me.getY () - startPt.y));

dg.setYmax (10 + DrawG.convertY (me.getY () - startPt.y));

//System.out.println("Xmin: "+DrawG.xmin);

//System.out.println("Xmax: "+DrawG.xmax);

//System.out.println("Ymin: "+DrawG.ymin);

//System.out.println("Ymax: "+DrawG.ymax);

repaint ();

}

public void mousePressed (MouseEvent me)

{

if (me.getSource () instanceof JComponent)

startPt = me.getPoint ();

}

public void mouseClicked (MouseEvent me)

{

}

public void mouseExited (MouseEvent me)

{

}

public void mouseEntered (MouseEvent me)

{

}

public void mouseReleased (MouseEvent me)

{

}

public static void main (String[] args)

{

Graph frame = new Graph ();

}

}

class DrawG extends JComponent

{

private String expression = "";

static double xmin = -10, xmax = 10, ymin = -10, ymax = 10;

static int Height = 500;

static int Width = 500;

double rx, ry; //number of pixels in one unit on the cartesian coordinates

int cx, cy; //coordinates of the orginal (in pixels)

public DrawG ()

{

xmin = -10.0;

xmax = 10.0;

ymin = -10.0;

ymax = 10.0;

setPreferredSize (new Dimension (500, 500));

setBorder (BorderFactory.createLineBorder (Color.black, 2));

setBackground (Color.white);

setVisible (true);

}

public void setExpression (String s)

{

if (expression.equals (s))

return;

if (s == null)

{

System.out.println ("Graph expression can't be null!");

return;

}

expression = s;

repaint ();

}

public static double convertX (int i) // convert pixels to cartesian coordinate

{

double x = (double) i / Width * (xmax - xmin) + xmin;

return x;

}

public static double convertY (int j) // convert pixels to cartesian coordinate

{

double y = (Height - (double) j) / Height * (ymax - ymin) + ymin;

return y;

}

public void setXmin (double x)

{

xmin = x;

}

public void setXmax (double x)

{

xmax = x;

}

public void setYmin (double y)

{

ymin = y;

}

public void setYmax (double y)

{

ymax = y;

}

public void paintComponent (Graphics g)

{

super.paintComponent (g);

int i, j1, j2;

rx = Width / (xmax - xmin);

ry = Height / (ymax - ymin);

cx = (int) (-xmin * rx);

cy = (int) (ymax * ry);

g.setColor (Color.red);

g.drawLine (cx, 0, cx, Height);

g.drawLine (0, cy, Width, cy);

}

}

andy_toka at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 5

here's your simplified code, simplified further :-), to just move the red cross-hairs around

(assuming that's what you're trying to do)

import java.awt.*;

import javax.swing.*;

import java.util.*;

import java.awt.event.*;

class Graph extends JFrame implements MouseListener, MouseMotionListener

{

DrawG dg;

public Graph ()

{

super ("Graph");

setSize (500, 600);

setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

dg = new DrawG ();

dg.addMouseListener (this);

dg.addMouseMotionListener (this);

getContentPane ().add (dg);

pack();setLocationRelativeTo(null);

setVisible (true);

}

Point startPt;

public void mouseMoved (MouseEvent me){}

public void mouseDragged (MouseEvent me)

{

Point newPt = me.getPoint();

dg.cx += newPt.x - startPt.x;

dg.ry += newPt.y - startPt.y;

startPt = newPt;

repaint ();

}

public void mousePressed (MouseEvent me)

{

startPt = me.getPoint ();

}

public void mouseClicked (MouseEvent me){}

public void mouseExited (MouseEvent me){}

public void mouseEntered (MouseEvent me){}

public void mouseReleased (MouseEvent me){}

public static void main (String[] args)

{

Graph frame = new Graph ();

}

}

class DrawG extends JComponent

{

int cx = 250, ry = 250;

public DrawG ()

{

setPreferredSize (new Dimension (500, 500));

setBorder (BorderFactory.createLineBorder (Color.black, 2));

setBackground (Color.white);

}

public void paintComponent (Graphics g)

{

super.paintComponent (g);

g.setColor (Color.red);

g.drawLine (cx, 0, cx, 500);

g.drawLine (0, ry, 500, ry);

}

}

Michael_Dunna at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 6
Thanks a lot!That's a nice demonstration and I finally figure out how to revise my program.
andy_toka at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 7
sorry, duplicate posterrorMessage was edited by: andy_tok
andy_toka at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 8

oops, not working. Sorry

I have to use setXmin(), setYmin and etc. because other parts of my program plot the graph based on xmin,xmax,ymin and ymax.

Michael_Dunn

Thanks for the replys! Am I bothering you again? :P

If you have time, can you correct my code below?

Sorry~

import java.awt.*;

import javax.swing.*;

import java.util.*;

import java.awt.event.*;

public class Graph extends JFrame implements MouseListener, MouseMotionListener

{

DrawG dg;

public Graph ()

{

super ("Graph");

setSize (500, 600);

setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

dg = new DrawG ();

dg.addMouseListener (this);

dg.addMouseMotionListener (this);

getContentPane ().add (dg);

pack ();

setLocationRelativeTo(null);

setVisible (true);

}

Point startPt;

public void mouseMoved (MouseEvent me)

{

}

public void mouseDragged (MouseEvent me)

{

dg.setXmin (dg.xmin - DrawG.convertX (me.getX () - startPt.x));

dg.setXmax (dg.xmax - DrawG.convertX (me.getX () - startPt.x));

dg.setYmin (dg.ymin + DrawG.convertY (me.getY () - startPt.y));

dg.setYmax (dg.ymax + DrawG.convertY (me.getY () - startPt.y));

repaint ();

}

public void mousePressed (MouseEvent me)

{

if (me.getSource () instanceof JComponent)

startPt = me.getPoint ();

}

public void mouseClicked (MouseEvent me)

{

}

public void mouseExited (MouseEvent me)

{

}

public void mouseEntered (MouseEvent me)

{

}

public void mouseReleased (MouseEvent me)

{

}

public static void main (String[] args)

{

Graph frame = new Graph ();

}

}

class DrawG extends JComponent

{

static double xmin, xmax, ymin, ymax;

static int Height = 500;

static int Width = 500;

double rx, ry; //number of pixels in one unit on the Cartesian coordinates

int cx, cy; //coordinates of the orgin (in pixels)

public DrawG ()

{

xmin = -10.0;

xmax = 10.0;

ymin = -10.0;

ymax = 10.0;

setPreferredSize (new Dimension (500, 500));

setBorder (BorderFactory.createLineBorder (Color.black, 2));

setBackground (Color.white);

setVisible (true);

}

public static double convertX (int i) // convert pixels to units

{

double x = (double) i / Width * (xmax - xmin);

return x;

}

public static double convertY (int j) // convert pixels to units

{

double y = (double) j / Height * (ymax - ymin);

return y;

}

public void setXmin (double x)

{

xmin = x;

}

public void setXmax (double x)

{

xmax = x;

}

public void setYmin (double y)

{

ymin = y;

}

public void setYmax (double y)

{

ymax = y;

}

public void paintComponent (Graphics g)

{

super.paintComponent (g);

rx = Width / (xmax - xmin);

ry = Height / (ymax - ymin);

cx = (int) (xmax * rx);

cy = (int) (ymax * ry);

g.setColor (Color.red);

g.drawLine (cx, 0, cx, Height);

g.drawLine (0, cy, Width, cy);

}

}

andy_toka at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 9
add the indicated line, in mouseDragged()dg.setYmax (dg.ymax + DrawG.convertY (me.getY () - startPt.y));startPt = me.getPoint();//<--repaint ();but somewhere you have reversed the x (drag mouse left, column line moves right)
Michael_Dunna at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 10

Thanks.

But if i change the paintComponent method to

public void paintComponent (Graphics g)

{

super.paintComponent (g);

rx = Width / (xmax - xmin);

ry = Height / (ymax - ymin);

cx = (int) (xmax * rx);

cy = (int) (ymax * ry);

g.setColor (Color.red);

g.drawLine (cx, 0, cx, Height);

g.drawLine (0, cy, Width, cy);

g.drawLine (cx+(int)(rx),0,cx+(int)(rx),Height);//add this line

}

It will draw a line perpendicular to the x-axis and the distance between this line and the y-axis should be (int)(rx) which is supposed to be a constant.

However, if you drag your mouse quickly to the right then to the left and do this several times, the distance between the two lines will become larger and larger! But why?

andy_toka at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 11

try this for mouseDragged

public void mouseDragged (MouseEvent me)

{

dg.setXmin (dg.xmin + dg.convertX (me.getX () - dg.cx));

dg.setXmax (dg.xmax + dg.convertX (me.getX () - dg.cx));

dg.setYmin (dg.ymin + dg.convertY (me.getY () - dg.cy));

dg.setYmax (dg.ymax + dg.convertY (me.getY () - dg.cy));

repaint ();

}

Michael_Dunna at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 12
Sorry, but it's weird that the gap between the two lines is still becoming bigger and bigger when you drag the mouse left and right fast enough.Did you see the same thing?
andy_toka at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 13

the same thing happens for me, but I was looking only at the mouse pointer.

prior to the changes in my last post, if you placed the pointer at the intersection,

then dragged up/down or left/right several times, the pointer would no longer

be at the intersection - because your formulas altered startPt.x

in my last post, I've used the converted points cx,cy as the start points.

Now, if you drag up/down or left/right, the pointer remains at the intersection,

which (I think) is what you want.

Michael_Dunna at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 14
Thanks!What i want is to move the graph when dragging. (the pointer is not necessarily at the intersection.) Do you have any idea about why the gap keeps increasing?
andy_toka at 2007-7-8 22:14:05 > top of Java-index,Desktop,Core GUI APIs...
# 15

the gap increases because after repositioning, startPt.x is set to where mouse.x is,

but paintComponent() does not paint at those coords - the formulas modify the

location slightly, so the next mouseDragged event uses startPt.x which is different

to the actual postion of cx.

>the pointer is not necessarily at the intersection.

yes, but I'd have thought you would want the relativity to remain

i.e. whereever the drag starts, if dragged left 20 pixels, the column line would

also move 20 pixels left

Michael_Dunna at 2007-7-21 16:36:23 > top of Java-index,Desktop,Core GUI APIs...
# 16
SO the increasing gap is due to the casting I used in convertX(), convertY() methods and other formulas?How to fix that then?
andy_toka at 2007-7-21 16:36:23 > top of Java-index,Desktop,Core GUI APIs...
# 17
go back to reply #11, I replaced startPt.x/y with the actual cx/cy values, which are thenrecalculated based on current mouse.x/y and converted to new cx/cy and redrawn
Michael_Dunna at 2007-7-21 16:36:23 > top of Java-index,Desktop,Core GUI APIs...
# 18
Does it work for you? because for me, the increasing gap still exists
andy_toka at 2007-7-21 16:36:23 > top of Java-index,Desktop,Core GUI APIs...
# 19

the increasing gap appears for me as well.

if you add this println(), then drag the cursor left/right numerous times,

the value of rx continually increases (regardless of going left or right), so the

gap increases as the value of rx increases

g.drawLine (cx+(int)(rx),0,cx+(int)(rx),Height);

System.out.println("cx="+cx+", rx="+rx+", cx+rx = "+(cx+(int)(rx)));

Michael_Dunna at 2007-7-21 16:36:23 > top of Java-index,Desktop,Core GUI APIs...
# 20
True. so am I supposed to round rx up so that the gap won't change?
andy_toka at 2007-7-21 16:36:23 > top of Java-index,Desktop,Core GUI APIs...
# 21
the only way the gap won't change is if the addition to cx is a constant value.//g.drawLine (cx+(int)(rx),0,cx+(int)(rx),Height);g.drawLine (cx+25,0,cx+25,Height);
Michael_Dunna at 2007-7-21 16:36:23 > top of Java-index,Desktop,Core GUI APIs...