Creating the draw line listener (2D)

Before we start writing source code for the listener class we should describe its functionality. (The posh name for this stage is called requirements analysis)

Requirements for listener class

  1. the background colour of the view changes when the mouse is over the view.
  2. show the [x, y] position of the mouse when it is over the view.
  3. draw a random line inside the view
  4. allow the user to draw a line using the mouse.

Now we are ready to start codeing. Lets create the class outline and add some attributes / fields for the view's data.

public class DrawLine extends GViewListener {
  // Background colours
  int[] back_col = { color(200, 255, 200), color(255, 255, 200) };
  // The colour to use
  int back_col_idx = 0;

  // The start and end positions of the line to be drawn
  int sx, sy, ex, ey;
  // Text description of mouse position i.e. [x, y]
  String mousePos;
  
  // Put any methods here in the class body

  
} // end of class body

Notice that this class extends the GViewListener class. The GViewListener class provides all the functionality you need to work with your view, making the program code you have to create much simpler.

Before going any further it is time to add our code to display the view contents. We need to add a method called update to our class. Here is the code

  public void update() {
    PGraphics v = getGraphics();
    v.beginDraw();
    v.background(back_col[back_col_idx]);
    if (sx != ex || sy != ey) {
      v.stroke(color(240, 0, 240));
      v.strokeWeight(10);
      v.strokeCap(ROUND);
      v.line(sx, sy, ex, ey);
    }
    v.fill(color(0));
    v.text(getMousePositionText(), 4, v.height - 4);
    v.endDraw();
    validate(); // view is current no need to update
  }

Important: All drawing commands view must be done inside this method.

Line No(s) Description
1 This is the method header and should be included as is.
2 This is strongly recommended. Getting a reference to the graphics object makes it simpler when creating multiple graphics atatements. You can see that in the lines that follow.
3 Since we are using a PGraphic object it is important to indicate when we want to start drawing using this statment.
4 Clears the graphics background with the colour specified in the array back_col[] at element position back_col_idx
5-12 Draws the line. Notice that all the commands are prefixed with v. so it uses the view rather that the sketch's main display.
13 Tell Processing we have finished drawing to the graphics object.
14 The call to validate() tells G4P not to update this view graphic until it has been invalidated.
15 End of method

So lets implement our first requirement 'the background colour of the view changes when the mouse is over the view'.

To do this we are going to make use of two events that are fired when the mouse enters and exits the view. So the following event handlers need to be added to our class.

  public void mouseEntered() {
    back_col_idx = 1;
    invalidate();
  }

  public void mouseExited() {
    back_col_idx = 0;
    invalidate();
  }

The methods are really very simple in that they change the value of back_col_idx which is used to change the views background colour. What is more interesting is the function call to invalidate() which tells G4P to call update() on the next frame.

This technique of validating the view at the end of the update() method and invalidating it only when a change occurs is very efficient.

We can also add our own methods to this class. Here are two methods I added

  /**
   Create a textual representation of the current mouse position
   */
  public String getMousePositionText() {
    return "Mouse @ [" + mouseX() + ", " + mouseY() + "]";
  }

  /**
   Create a line in a random position in the view
   */
  public void randomLine() {
    sx = round(random(width()));
    sy = round(random(height()));
    ex = round(random(width()));
    ey = round(random(height()));
    invalidate();
  }

The first one is a simple helper function and we can see it being used in line 12 of the update method.

The second function randomLine() simply provides random start and end positions for the line and then calls invalidate() so the view will be updated to draw the new line.

Requirement 2, 'show the [x, y] position of the mouse when it is over the view' is simple to implement because the update method already displays the current mouse position. All we need to do is invalidate the view when the mouse moves like this.

  public void mouseMoved() {
    invalidate();
  }

So the last methods we are going to look at are those for the final requirement, 'allow the user to draw a line using the mouse'.

  public void mousePressed() {
    sx = ex = mouseX();
    sy = ey = mouseY();
    invalidate();
  }

  public void mouseDragged() {
    ex = mouseX();
    ey = mouseY();
    invalidate();
  }

Notice the use of invalidate() to force G4P to update the view.

These event handler methods are analogous to the ones you have used in your processing sketch but inside your class they only apply to your view.

Look at the GViewListener API guide for a full listing of methods you can use and what they mean but here are the ones used in this sketch

Program statement in the listener class Description
onMouseEntered()
onMouseExited()
Event handlers for when the mouse enters or leaves the view. The equivalent methods used in the main sketch code are executed when the mouse enters or leaves the application (sketch).
width()
height()
Similar to Processing's width and height but they return the width and height of the view.
mouseX()
mouseY()
pmouseX()
pmouseY()
Equivalent to mouseX, mouseY, pmouseX and pmouseY but the mouse positions are relative to the top-left corner of the view.

Once the listener is created we can simply add it to the view in setup() ...

  // Setup 2D view and listener
  view2D = new GView(this, 30, 24, 260, 200, JAVA2D);
  viewer2D = new DrawLine();
  view2D.addListener(viewer2D);