2

I'm new at using actionListener and mouselistner. I want to track the Mouse movements and connect the dots as I go. So it will be one continuous line. I am using the MouseMotionListener every time I move the mouse across the screen and get a new set of points. I am not using mousePressed or mouseReleased.

Everytime I move the mouse, I can get every point of where my mouse's position is on my JPanel to show up on my results window, but in order to draw the line between two points, I'm not sure how to decipher between each different set of points so I can have a beginning and ending set of points to use for drawing a line? I checked through here and the API and I'm stuck.

I was asked to put more code and so I gave you my code.

I am basically creating a Jpane that tracks mouse movement when the Track Mouse button or Draw Track Radio button is pressed These results will print out as (x,y) on the output screen

FYI: You can also draw circles once the Draw circles RadioButton is checked

Jpanel Output

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

public class MouseTest {

private JFrame frame;
private boolean tracking;
private boolean drawing;
private boolean connectdots;
private int xstart;             
private int ystart;             
private int xend;   
private int y;              
private int x;  
private int yend;               
private int borderWidth = 5;    
String drawCircles = "Draw Circles";
String drawTrack = "Draw Track";

public static void main (String [] arg) {
    MouseTest first = new MouseTest(); 
}//main

$

public MouseTest() {
    tracking = false; 
    frame = new JFrame(); 
    frame.setBounds(250,98,600,480);
    frame.setTitle("Window number three");
    Container cp = frame.getContentPane();
    JButton track = new JButton("Track Mouse");
    track.addActionListener(new ActionListener() {    

        public void actionPerformed(ActionEvent ae) {
            trackMouse();
        }
    });

    JPanel top = new JPanel();
    top.add(track);
    cp.add(top,BorderLayout.NORTH);

    MyPanel pane = new MyPanel();

    cp.add(pane,BorderLayout.CENTER);
    pane.addMouseListener(new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
            xstart = e.getX();
            ystart = e.getY();
        }
        public void mouseReleased(MouseEvent e) {
            xend = e.getX();
            yend = e.getY();
            if (xend < xstart) { int tmp = xstart; xstart = xend; xend = tmp; } 
            if (yend < ystart) { int tmp = ystart; ystart = yend; yend = tmp; } 
            frame.repaint();
        }
    });
    pane.addMouseMotionListener(new MouseMotionAdapter() { 
        public void mouseMoved(MouseEvent e) { 
            if (tracking) { 
                x = e.getX();  
                y = e.getY();
                msg("(" + x + ", " + y + ")");
            }
        }
    });

    JRadioButton circleButton = new JRadioButton(drawCircles);
    circleButton.setMnemonic(KeyEvent.VK_B);
    circleButton.setActionCommand(drawCircles);
    circleButton.setSelected(false);

    JRadioButton trackButton = new JRadioButton(drawTrack);
    trackButton.setMnemonic(KeyEvent.VK_C);

    ButtonGroup group = new ButtonGroup();
    group.add(circleButton);
    group.add(trackButton);

    JPanel radioPanel = new JPanel(new GridLayout(2,0)); 
    radioPanel.add(circleButton);
    radioPanel.add(trackButton);    
    cp.add(radioPanel,BorderLayout.EAST);
    drawing = false;
    connectdots = false;

    circleButton.addActionListener(new ActionListener() { //Set drawing to true when the button is clicked
        public void actionPerformed(ActionEvent ae) {
            tracking = !tracking;
            drawCircles();
        }
    });

    trackButton.addActionListener(new ActionListener() { //Set drawing to true when the button is clicked
        public void actionPerformed(ActionEvent ae) {
            drawing = false;
            tracking = true;
            connectDots();
        }   
    });

    frame.setVisible(true);
}//constructor

$

public void trackMouse() {  
        tracking = !tracking;
}//trackMouse

public void msg(String s) { //new method to simplify the system.out.print method
    System.out.println(s);
}

public void drawCircles() { 
    drawing = true;

}//Allow Drawing of Circles

public void connectDots() { 
    connectdots = !connectdots;

}//Trying to use for connecting the mouse motion listener points when tracking

$

public class MyPanel extends JPanel {        

    ArrayList<Circle> circles = new ArrayList<Circle>();


public void paintComponent(Graphics g) {

    int width  = this.getWidth();
    int height = this.getHeight();

    msg("H = " + height + ",  w = " + width);
    g.setColor(Color.BLACK);
    Circle c = new Circle(xstart, ystart);   

    circles.add(c);
    if (drawing){  
        for(int k=0; k<circles.size(); k++){
            circles.get(k).draw(g);
        }
    }           // draw the circle

    if (connectdots && tracking) { //trying to use for drawing the lines
        g.drawLine(x,y,x,y);
    }

    for (int delta = 0; delta < borderWidth; delta++) {

        g.drawRect(delta,delta,width-(2*delta),height-(2*delta));

    }
    if (xstart != xend || ystart != yend) {    
        int red     = (int)(256*Math.random());
        int green   = (int)(256*Math.random());
        int blue    = (int)(256*Math.random());
        g.setColor(new Color(red, green, blue));
        msg("Colors are:  " + red + " - " + green + " - " + blue );
        msg("Drawing from: (" + xstart + ", " + ystart + ") to (" + xend + ", " + yend + ")");
        msg("Width is " + (xend-xstart) + " -  Height is " + (yend-ystart));
        g.fillRect(xstart,ystart,xend-xstart,yend-ystart);
    }

}
}
}

$

public class Circle {

// instance variables:
int radius;  //random radius
int x, y;  // coords of the center point
private Graphics g;


public Circle(int xIn, int yIn) {
    radius = (int)(127*Math.random());
    x = xIn;
    y = yIn;

}    

public void draw(Graphics g){
    g.drawOval(x-radius, y-radius, radius, radius);
    g.fillOval(x-radius, y-radius, radius, radius);
    int red     = (int)(256*Math.random());
    int green   = (int)(256*Math.random());
    int blue    = (int)(256*Math.random());
    g.setColor(new Color(red, green, blue));
}

public int getX(int xstart) {
    // TODO Auto-generated method stub
    return x;
}

public int getY(int ystart) {
    // TODO Auto-generated method stub
    return y;
}
}
handro
  • 85
  • 6
  • 13
  • 2
    You need to provide more information. If you aren't using mouse clicks, and you are getting one point from the mouse coordinates, then where does the other point come from? – DNA Feb 18 '12 at 23:47
  • I think you'll need to tell us a lot more. What does your GUI look like? What components have the MouseMotionListener added to them? Can you create and post an [sscce](http://sscce.org) (please click on the link), otherwise how will we have any clue as to what you're doing wrong? – Hovercraft Full Of Eels Feb 18 '12 at 23:48
  • Ok thank you, I can do that. Last time I put in a lot of information even though I was 95% complete, I got an email saying that it wasn't fair to ask this site to do my homework for me, so I am going to include as much as I can following the sscce guidelines and try not to over do it. – handro Feb 19 '12 at 00:00
  • Thanks for the edit, but I think that you'll need a bit more code to make it an [sscce](http://sscce.org). Again, please read the specification in the link and you'll see that the code should be small, but should be compilable and runnable and demonstrate your error. The code above doesn't directly show any problems that are referable to your problem just yet. – Hovercraft Full Of Eels Feb 19 '12 at 00:03
  • @HovercraftFullOfEels I think you misunderstood him. His code is working, he just can't get around drawing his line because he only has one point on each motion event. – kaoD Feb 19 '12 at 00:20
  • @kaoD: Perhaps you're right. that's easily identified with an SSCCE and solved with an `ArrayList`. – Hovercraft Full Of Eels Feb 19 '12 at 00:21
  • OK,.... please re-read the link on SSCCE. The first word is "short" and that means posting a *minimal* example that demonstrates your problem. For an example, please look at my code below. It is small, self contained and runs. – Hovercraft Full Of Eels Feb 19 '12 at 00:45
  • Also, just what are you trying to draw? A single straight line that connects two points (if so, what do the two points represent)? Or a curve that shows the path of the mouse after the tracking button (which probably should be a JToggleButton) has been pressed? – Hovercraft Full Of Eels Feb 19 '12 at 00:57
  • Great question. I just want to draw a straight line connecting the two points. So it will end up kind of like a crazy ecthasketch drawing. – handro Feb 19 '12 at 01:00
  • I created a radio button so that when it's checked it will start the mouse tracking and connecting of the dots with the straight line. Just trying to get the connecting of the dots to work. Trying an Array list. – handro Feb 19 '12 at 01:01
  • see example 2 in my answer below – Hovercraft Full Of Eels Feb 19 '12 at 05:31

2 Answers2

3

An example of an sscce:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class Foo3 extends JPanel {
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private boolean tracking = false;
   private int x, y;

   public Foo3() {
      add(new JToggleButton(new AbstractAction("TrackMouse") {
         public void actionPerformed(ActionEvent ae) {
            trackMouse(ae);
         }
      }));

      MyMouseAdapter myMA = new MyMouseAdapter();
      addMouseMotionListener(myMA);
   }

   private void trackMouse(ActionEvent ae) {
      JToggleButton toggleBtn = (JToggleButton) ae.getSource();
      tracking = toggleBtn.isSelected();
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   public void msg(String message) {
      System.out.println(message);
   }

   private class MyMouseAdapter extends MouseAdapter {
      @Override
      public void mouseMoved(MouseEvent e) {
         if (tracking) { 
            x = e.getX();
            y = e.getY();
            msg("(" + x + ", " + y + ")");
         }
      }
   }

   private static void createAndShowGui() {
      Foo3 mainPanel = new Foo3();

      JFrame frame = new JFrame("MouseMotion Eg");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

Edit: Example 2

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.*;

@SuppressWarnings("serial")
public class MouseTestHovercraft extends JPanel {
   private static final int PREF_W = 600;
   private static final int PREF_H = PREF_W;
   private static final int MAX_CLR = 5;
   private static final Color CURRENT_LIST_COLOR = new Color(190, 190, 255);
   private List<Color> colors = new ArrayList<Color>();
   private boolean tracking = false;
   private List<Point> currentList = null;
   private BufferedImage bufferedImage = new BufferedImage(PREF_W, PREF_H,
         BufferedImage.TYPE_INT_ARGB);
   private Random random = new Random();

   public MouseTestHovercraft() {
      for (int redIndex = 0; redIndex < MAX_CLR; redIndex++) {
         int r = (redIndex * 256) / (MAX_CLR - 1);
         r = (r == 256) ? 255 : r;
         for (int greenIndex = 0; greenIndex < MAX_CLR; greenIndex++) {
            int g = (greenIndex * 256) / (MAX_CLR - 1);
            g = (g == 256) ? 255 : g;
            for (int blueIndex = 0; blueIndex < MAX_CLR; blueIndex++) {
               int b = (blueIndex * 256) / (MAX_CLR - 1);
               b = (b == 256) ? 255 : b;
               Color c = new Color(r, g, b);
               colors.add(c);
            }
         }
      }

      add(new JToggleButton(new AbstractAction("TrackMouse") {
         public void actionPerformed(ActionEvent ae) {
            trackMouse(ae);
         }
      }));
      add(new JButton(new AbstractAction("Clear Image") {
         public void actionPerformed(ActionEvent e) {
            bufferedImage = new BufferedImage(getWidth(), getHeight(),
                  BufferedImage.TYPE_INT_ARGB);
            repaint();
         }
      }));

      MyMouseAdapter myMA = new MyMouseAdapter();
      addMouseListener(myMA);
      addMouseMotionListener(myMA);
   }

   private void trackMouse(ActionEvent ae) {
      JToggleButton toggleBtn = (JToggleButton) ae.getSource();
      tracking = toggleBtn.isSelected();
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   public void msg(String message) {
      System.out.println(message);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.drawImage(bufferedImage, 0, 0, null);
      if (currentList != null) {
         drawList(g, currentList, CURRENT_LIST_COLOR, 1f);
      }
   }

   private void drawList(Graphics g, List<Point> ptList, Color color,
         float strokeWidth) {
      if (ptList.size() > 1) {
         Graphics2D g2 = (Graphics2D) g.create();
         g2.setColor(color);
         g2.setStroke(new BasicStroke(strokeWidth));
         for (int j = 0; j < ptList.size() - 1; j++) {
            int x1 = ptList.get(j).x;
            int y1 = ptList.get(j).y;
            int x2 = ptList.get(j + 1).x;
            int y2 = ptList.get(j + 1).y;
            g2.drawLine(x1, y1, x2, y2);
         }
         g2.dispose();
      }
   }

   private class MyMouseAdapter extends MouseAdapter {

      @Override
      public void mousePressed(MouseEvent e) {
         if (tracking && e.getButton() == MouseEvent.BUTTON1) {
            currentList = new ArrayList<Point>();
            currentList.add(e.getPoint());
         }
      }

      @Override
      public void mouseReleased(MouseEvent e) {
         if (tracking && e.getButton() == MouseEvent.BUTTON1) {
            currentList.add(e.getPoint());
            Graphics2D g2 = bufferedImage.createGraphics();
            Color color = colors.get(random.nextInt(colors.size()));
            drawList(g2, currentList, color, 3f);
            currentList = null;
            repaint();
         }
      }

      @Override
      public void mouseDragged(MouseEvent e) {
         if (tracking && currentList != null) {
            currentList.add(e.getPoint());
            repaint();
         }
      }
   }

   private static void createAndShowGui() {
      MouseTestHovercraft mainPanel = new MouseTestHovercraft();

      JFrame frame = new JFrame("MouseMotion Eg");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.setResizable(false);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
3

You just have to save x and y in some attribute for your class (like lastX and lastY.) When you get the event the second time, your first point coordinates are saved in your attributes and you can then draw your line. This new point has to be saved too to serve as your new lastX and lastY.

Even better: since you'll probably need to redraw your lines each frame (if you want a set of lines and not just a single line to be drawn each frame), use Point to save your coordinates and some kind of list like ArrayList. Save the full set of tracked points in an ArrayList<Point> and then draw each frame iterating over this list.

kaoD
  • 1,534
  • 14
  • 25
  • 1+ for your good suggestion. He'll need to override `paintComponent(...)` and iterate through his attribute (again, likely a list of some sort), drawing each line as he goes through the loop. – Hovercraft Full Of Eels Feb 19 '12 at 00:25
  • @HovercraftFullOfEels you're right. I thought he just wanted to draw one line in each frame, not the whole set of lines. I updated my answer to reflect both goals. – kaoD Feb 19 '12 at 00:31
  • truthfully, I'm not sure what he wants. – Hovercraft Full Of Eels Feb 19 '12 at 00:32
  • Sorry for not being clearer. I want to track the Mouse movements and connect the dots as I go. So it will be one continuous line. I am going to try the arraylist like I did with my circles. Not sure why I didn't think of that. Thank you. – handro Feb 19 '12 at 00:55
  • @kaoD I got the Points to Store in a Arraylist, but I'm not sure how to pass them as parameters into a draw method. Is there a draw method that uses Point objects as a parameter? – handro Feb 19 '12 at 01:29
  • @handro not that I know of, but the `Point` object is easier to pass around than two separate `int`s and it serves a clear purpose (it's obvious it's a point, which is great for code readability.) X and Y attributes are public in `Point`, so just grab them to feed `drawLine`. – kaoD Feb 19 '12 at 01:39
  • @handro: you simply iterate through the ArrayList in the paintComponent method. – Hovercraft Full Of Eels Feb 19 '12 at 01:52
  • @kaoD and @Hovercraft Full Of Eels, thank you both for your help. I was able to get it to work and it's pretty sweet. I'm not completely 100% sure what my teacher wants and so I have it connecting the dots with Mouse press and releases and with the tracking (Mouse Motion Listener). I used `points` in an Arralylist to store the x and y's. Then I put those values into 2 `for` loops and used the `drawLine` method and turned the x and y into `int`s and it worked. – handro Feb 19 '12 at 23:44
  • @kaoD. I thought I had it but I've been trying to iterate through the ArrayList in the paintComponent method and I'm truly not familiar with that. I took `points.add(new Point(x,y));` and put it into an `Iterator litr = points.iterator();` and I tried plugging that into a `while` loop to get the `litr.next()`, but I don't know how to put that into the `Graphics` `drawLine(int x1, int y1, int x2, int y2)` method to draw the line. It just sees it as one object vs the seperate x and y components within the `Point` object. – handro Feb 20 '12 at 03:36