Mouse Interaction, Array, ArrayList, and Geom Shapes
______________________________________________________________________________________
SCHOOL OF floatERACTIVE ARTS + TECHNOLOGY [SIAT] | WWW.SIAT.SFU.CA
Copyright By PowCoder代写 加微信 powcoder
Mouse Interactions
– MouseListener, MouseEvent, MouseAdapter
Data structures
– Array for storing object collection – ArrayList for removing/adding
Drawing with Graphics2D and geoms
– Graphics2D’s draw/fill methods
– Classes in geom package for geometric shapes
10/1/2021 IAT 265 2
Mouse Interactions
Two groups: clicking and moving
– Can be initiated using different mouse buttons
– Can be accompanied with modifier keys being pressed (Shift, Ctrl, Alt, etc. or their combination)
There are two corresponding listeners: MouseListener and MouseMotionListener
10/1/2021 IAT 265 3
MouseListener Interface What are the events of interest?
– mouseClicked
– Although it declares total five methods
Callback method for mouseClicked
– public void mouseClicked(MouseEvent e)
MouseEvent object
– Give access to event context (location, clicks,
modifier keys, etc….)
10/1/2021 IAT 265 4
MouseEvent class methods getX(), getY() – returns coordinates of mouse
getClickCount() – returns mouse clicks, e.g. 2 for double-clicks
10/1/2021 IAT 265 5
Let’s move ladybug to where we click
JPanel should implement MouseListener
1. NeedstoimplementmouseClicked()–retrieves
mouse coordinates from MouseEvent object
2. Allotherinterfacemethodswillbeimplemented
as dummies (i.e. empty body)
3. JPanelwillregistertolistentomouseevents:
• By calling addMouseListener(MouseListener ml), a method belongs to java.awt.Component, of which JPanel is a subclass
Recap: Java Classes for Rendering
Two types of GUI elements:
JPanel as a subclass of Component can call the method
Class that defined
addMouseListener (MouseListener ml)
October 1, 2021 IAT 265 7 • Source of the diagram: http://www.ntu.edu.sg/home/ehchua/programming/java/J4a_GUI.html#zz-2.2
BugPanel code
class BugPanel extends JPanel
implements ActionListener,
//implements *ALL* methods
declared by MouseListener
public void
mouseClicked (MouseEvent e){
bug.setLocationX(e.getX());
bug.setLocationY(e.getY());
//update the display
repaint();
MouseListener {
private Ladybug bug;
private Timer timer;
//constructors
public BallPanel() {
//register listeners timer.addActionListener(this); this.addMouseListener(this);
//All the rest is the same as
public void
mousePressed(MouseEvent e) {}
public void
mouseReleased(MouseEvent e){}
Our Goal next …
Stop the bug when mouse is clicked on it
Resume its moving when mouse is double
clicked on it
Otherwise, reset its location to where mouse is clicked
10/1/2021 IAT 265 9
Stop ladybug when clicked
Let’s do some analyses: How bug moves?
How to stop it?
if(isMoving) bugX += speedX;
isMoving = false;
IAT 265 10
bugX += speedX;
– When clicked
public void mouseClicked(MouseEvent e){
Resume with double-clicks
When double-clicked, we can check it out in the same mouseClicked method
public void mouseClicked(MouseEvent e) {
isMoving = false; //if single click
if(e.getClickCount() > 1) //if double click
isMoving = true;
10/1/2021 IAT 265 11
In Laybug class:
Reset its location when clicked off
When mouse clicked off the bug’s body, we can simply call its location setter methods and set them to the mouse cursor position
public void setLocationX(int x) {
public void setLocationY(int y) {
Per our analysis so-far, it feels like it would be convenient that we make Ladybug implement MouseListener, rather than JPanel
– Would this work? Let’s try!
10/1/2021 IAT 265 12
What went wrong …
Remember addMouseListener is defined by Component, therefore can only be invoked by an object of its subclasses
– JPanel is such a subclass
Ladybug is our custom class, an
independent class
– NOT a subclass of Component
10/1/2021 IAT 265 13
The correct way …
Implement MouseListener with BugPanel How do we know that the bug was clicked?
– We need to check the coordinates to see if mouse point hits the bug (at its current location)
– Which object knows where the bug was located?
• Ladybug! We need to check within Ladybug if it was hit
• Also isMoving should be a field of LadyBug, so that we can set it up inside the class with a method like bugClicked(MouseEvent e)
10/1/2021 IAT 265 14
BugPanel code
Ladybug code
public class Ladybug {
public boolean checkBugHit(int x,
class BugPanel extends JPanel
implements ActionListener,
MouseListener {
//All the rest is the same as
boolean hit = false;
if(Math.abs(bugX – x) <
before ...
public void
mouseClicked (MouseEvent e){
int mouseX = e.getX();
int mouseY = e.getY();
(bodyW/2)*scale &&
} bug.setLocationY(mouseY);
if (e.getClickCount() > 1)
isMoving = true;
if (bug.checkBugHit(mouseX,
bug.bugClicked(e);
Math.abs(bugY – y) <
(bodyH/2)*scale))
hit = true;
} return hit;
public void bugClicked(MouseEvent
bug.setLocationX(mouseX);
isMoving = false;
Let’s drag the bug...
We need MouseMotionListener , which declared two methods
– mouseDragged(MouseEvent e) - called for each new location while dragging
– mouseMoved(MouseEvent e) - called for each new location while moving
10/1/2021 IAT 265 16
BugPanel code
class BugPanel extends JPanel
implements ActionListener,
MouseListener,
MouseMotionListener {
this.addMouseMotionListener(this);
//All the rest is the same as
public void
mouseDragged(MouseEvent e){
if (bug.checkBugHit(e)){ bug.setLocationX(e.getX()); } } bug.setLocationY(e.getY());
public void
mouseMoved(MouseEvent e){}
10/1/2021 IAT 265 17
Let’s change bug size ...
When clicked with Shift, enlarge
When clicked with Ctrl, shrink
How to check these modifier keys?
10/1/2021 IAT 265 18
Checking modifier keys
InputEvent class provides these relevant methods, and MouseEvent is one of its subclasses:
– boolean isShiftDown()
– boolean isControlDown() – boolean isAltDown()
To test for a flag, check if one of these methods tests true, e.g.:
if(e.isShiftDown()) ...
IAT 265 19
BugPanel code
class BugPanel extends JPanel implements ActionListener,
MouseListener {
//All the rest is the same as before
//enlarge by 20%
//shrink by 20%
public void
mouseClicked (MouseEvent e){
if(bug.checkBugHit(e) && (e.isShiftDown()){
bug.enlarge();
if( bug.checkBugHit(e) && (e.isControlDown()){
bug.shrink();
//All the rest is the same as before
10/1/2021 IAT 265 20
Adapter classes for Listener Interfaces
Why Adapter classes?
– When implementing Listener interface, you must implement all of its methods even though your program does not care about some of them
– For convenience, Java provides supporting classes – Adapters, which provide "dummy implementations" for all the methods declared in the corresponding interface
– By "extends" from the adapter class, you only need to override the method you want with your own implementation
10/1/2021 IAT 265 21
Adapters for listener interfaces
Adapter class
implemented
WindowAdapter
WindowListener
MouseAdapter
MouseListener
MouseMotionAdapter
MouseMotionListener
KeyAdapter
KeyListener
FocusAdapter
FocusListener
10/1/2021 IAT 265 22
MouseMotionAdapter class
public interface MouseMotionListener {
public void mouseDragged (MouseEvent e); public void mouseMoved (MouseEvent e);
public abstract class MouseMotionAdapter implements MouseMotionListener {
public void mouseDragged (MouseEvent e) { }
public void mouseMoved (MouseEvent e) { }
10/1/2021 IAT 265
MouseAdapter class
public Interface MouseListener {
public void mousePressed (MouseEvent e); public void mouseReleaseed (MouseEvent e); public void mouseClicked(MouseEvent e); public void mouseEntered(MouseEvent e); public void mouseExited(MouseEvent e);
public abstract class MouseAdapter implements MouseListener {
//Can you fill in the implementation here?
10/1/2021 IAT 265 24
How to use Adapter classes for Listening?
Typically, we need to define our custom listener classes as inner classes by extending the relevant Adapter classes
– This is necessary as listening is usually implemented in the panel class, which extends JPanel class already, and therefore cannot extend any other class
– For inner classes though, you can define as many as necessary within the panel class, each of which can extend from a relevant Adapter class
10/1/2021 IAT 265 25
Define Custom Inner Listener classes
In BugPanel class, define two inner private classes for mouse and mouse motion listening that extend MouseAdapter and MouseMotionAdapter
private class MyMouseMotionListener extends MouseMotionAdapter {
private class MyMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent e){ ...
if(bug.checkBugHit(mouseX, mouseY)
&& e.isShiftDown(){
} bug.enlarge();
public void mouseDragged(MouseEvent e){ int mouseX = e.getX();
int mouseY = e.getY();
bug.setLocationY(mouseY); }}
if(if(bug.checkBugHit(mouseX, mouseY) && e.isControlDown() {
if (bug.checkBugHit(mouseX, mouseY)){ bug.setLocationX(mouseX);
bug.shrink();
} } bug.setLocationY(mouseY);
if (bug.checkBugHit(mouseX, mouseY)){
bug.clicked(e);
bug.setLocationX(mouseX);
Instantiate and add Custom Listener object
In BugPanel’s constructor, instantiate the two custom mouse listener classes and add them to BugPanel
public class BugPanel extends JPanel implements ActionListener { ... //here is the same as before
public BugPanel(){
... //here is the same as before
MyMouseMotionListenermyMoMoLsner =newMyMouseMotionListener();
addMouseMotionListener(myMoMoLsner);
MyMouseListener myMoLsner = new MyMouseListener();
addMouseListener(myMoLsner); }
10/1/2021 IAT 265 27
Recap: Array
An array is a contiguous collection of data items of a single type
– An array stores a list of values (aka elements) – Values are accessed by index numbers
• Array index counts from 0, and ends at array_length-1 – You can get the length of an array by:
arrayName.length
10/1/2021 IAT 265 28
Array of Primitives
int [] nums = new int[7] ;
10/1/2021 IAT 265
Syntax for creating an array of
primitives
// declare a double array
double[] floatArray;
// allocate memory space
for the array
floatArray = new double[5];
Name: floatArray, Type: double[] null
01234 01234 01234
// set first element
floatArray[0] = 3;
// set third element
floatArray[2] = 5; 10/1/2021
IAT 265 30
Array of objects
Instantiate and initialize the array itself: Dog[] pets = new Dog[7];
It starts as an array of null reference for each element
10/1/2021 IAT 265
Array of objects
Dog[] pets = new Dog[7] ;
//Initialize each elements pets[0] = new Dog(); pets[1] = new Dog();
If you forget this step
Null pointer exception!!
Case study:
handle a collection of bugs
Create a collection of bugs with different sizes and random movement
Involve arrays, randomness, transformations, and saving/restoring transform attributes
IAT 265 33
First off ...
For convenience, let’s create a Util class, which defines a random method with range parameters:
public class Util {
public static double random(double low, double high) { }return low + Math.random() * (high - low);
public static float random(float low, float high) { }return (float) (low + Math.random() * (high - low));
10/1/2021 IAT 265 34
Create an Array of Bugs in BugPanel
//declare the Bug array
private Ladybug[] bugs;
Private final static int BUG_COUNT = 30;
//constructor: create the Bug array
bugs = new Ladybug[BUG_COUNT];
//and fill it with Bug objects
for (int i = 0; i < bugs.length; i++) {
float scale = Util.random(0.4f, 1.2f);
float spdX = Util.random(-2.0f, 2.0f);
float spdY = Util.random(-2.0f, 2.0f);
float locX = GARDEN_X + Util.random(50, GARDEN_W); float locY = GARDEN_Y + Util.random(50, GARDEN_H);
bugs[i] = new Ladybug(new Pvector(locX, locY), new Pvector(spdX, spdY), scale);
10/1/2021 IAT 265 35
Loop through the array to render and move these bugs
public void paintComponent(Graphics g) { //whatever done before
//Loop through the array to draw the bugs one by one
for (int i = 0; i < bugs.length; i++) {
bugs[i].drawBug(g2);
public void actionPerformed(ActionEvent e) {
//Loop through the array to move the bugs one by one
for (int i = 0; i < bugs.length; i++) { } bugs[i].move();
repaint();
10/1/2021 IAT 265 36
Summary on Array
Arrays are collections of data of certain type, which is specified when the array is declared
Each array must specify a size when declared
An array’s size can be retrieved with
arrayName.length
For Array of objects
– When we declare and initialize an array of objects, the array is empty. it has a size, but doesn't contain any object yet but null
– Not until we've initialized each element of the array can we say that our array contains objects
– Only when each element in the array has be initialized
with an object, we can then use this array in other portion
of our program
10/1/2021 IAT 265 37
What if number of objects is changing?
Say we want to remove by double-clicking the bug, add Ladybug by double-clicking the panel
When storing bugs in an array, there are several problems:
– Remove: we need to either set array cell to null or set a dead flag
in Bug to avoid its drawing/moving/interacting in frame looping – Where in the array to add a new bug? Either fill in null spots or
replace dead ones
– What if the array is full and we want to add new ones?
If an array is causing trouble, is there other way to store our objects?
10/1/2021 IAT 265 38
A more flexible alternative: ArrayList
It’s a resizable array that holds objects
– Can add and delete things without worrying about
declaring the size
The main methods we care about are: add(Object o), get(int i), remove(Object o), and size()
– Unlike an array, you call ArrayList’s size() method to get its length
10/1/2021 IAT 265 39
Note to add(Object o)method The parameter type of add method is Object
– Object is the root of Java class hierarchy every Java class has Object as the ancestry superclass (implicitly!)
– When a parameter is typed with Object, you can pass in an object of any class (broadest Inclusion Polymorphism!!)
So, to initialize our bugs ... ArrayList bugs = new ArrayList();
for(int i = 0; i < count; i++){
bugs.add(new Ladybug(...));
10/1/2021 IAT 265 40
Getting things out of an ArrayList
get(int i) – returns the ith object (starting with 0)
But the following doesn’t work! Ladybug bugi = bugs.get(i);
bugi.drawBug(g2);
10/1/2021 IAT 265 41
Ways to deal with Type issue for ArrayList
This is because: things are placed into an ArrayList as Object type, and taken out as Object type as well – agnostic to their more specific type
– Object doesn’t know any method it doesn’t define
Generally there are two ways to deal with the issue:
– Type Casting back to the more specific type when you take things out of an ArrayList
– When you create an ArrayList object, specify the type with <> operator
10/1/2021 IAT 265 42
Examples for both
Type Casting back to the more specific type: for(int i=0; i < bugs.size(); i++){
Ladybug bugi =(Ladybug)bugs.get(i);
bugi.drawBug(g2);//works fine now!
Specify Type when declaring ArrayList objects: ArrayList
10/1/2021 IAT 265 43
Destroy bugs with ArrayList’s remove method
When a Bug object is double-clicked, we need to destroy it
– Add a destroy method to the BugPanel class:
bugs.remove(b); //note we do not need to know the index
By doing so, any dead one would be removed ArrayList’s size() method will return new size
10/1/2021 IAT 265 44
Case study: Remove/Add a Bug via ArrayList
By double clicking on the bug/window
10/1/2021 IAT 265 45
Define Custom Inner Listener classes
In BugPanel class, define an ArrayList to hold bugs
In the inncer class’ mouseClicked method to handle bug
removal/addition with double click
pubic class BugPanel implements ActionListener {
private ArrayList
//all others the same as before
public BugPanel(){
bugs = new ArrayList
for (int i = 0; i < BUG_COUNT; ++i) { ... //same as previous example
bugs.add(new Bug(loc, vel, scale)); }}
public void mouseClicked(MouseEvent e){ if (e.getClickCount() < 2)
return; //done if no double click
Bug bugi = null;
for (int i = 0; i < bugs.size(); ++i){
if (bugi != null) //if hits a bug
bugs.remove(bugi);
else //Or hits none } respawNewBug();
if(bugs.get(i).checkBugHit(e.getX(), e.getY())){
bugi = bugs.get(i); //if identify one } break; //break out of loop
Summary on ArrayList
ArrayList allows you to create a dynamically resizable list
ArrayList elements are typed with Java root class Object by default , as a result it is agnostic to the specific type of objects it holds
You can choose to specify the type when declaring an ArrayList object with
Otherwise when getting elements out of an ArrayList you must cast them back to their specific type before you can call their methods or access their fields
10/1/2021 IAT 265 47
Recap: Graphics2D
Graphics2D class is a newer, more powerful
version drawing tool than Graphics class
– It draws or fills primitives in a more flexible way
– It can draw more primitives than its parent class, e.g. curves
– It has functionality for checking intersection and containment between objects
(Done with the followings)
– It can draw with better quality (anti-aliasing)
– It provides transformation functionalities (translate,
rotate, scale etc.) that its parent class is unable to do
October 1, 2021 IAT 265 48
Review: Graphics’ methods for drawing primitives
– drawLine(int x1, int y1, int x, int y2) – drawRect(int x1, int y1, int w, int h)
– fillRect(int x1, int y1, int w, int h)
– drawOval(int x1, int y1, int w, int h)
– fillOval(int x1, int y1, int w, int h)
– drawArc(int x1, int y1, int w, int h, int startAngle, int arcAngle)
– fillArc(int x1, int y1, int w, int h , int startAngle, int arcAngle) – drawPolygon(int xArray[], int yArray[], int numPoints)
– fillPolygo(int xArray[], int yArray[], int numPoints)
Have you noticed any problem with these drawing methods
October 1, 2021 IAT 265 49 References: Images from 7 Surefire Articles to Help You Save Money at the Gas Pump
of Graphics object?
Working with Graphics2D and Geometric Classes
It would be desirable to have only two methods instead:
– draw (shape); – fill (shape);
Where shape is a geometric object passed in as argument, rather than coupled with method name
October 1, 2021 IAT 265 50 References: Images from https://www.redfynn.com/gas-station
What is this?
Shapes in java.awt.geom
Sowhatwecandonowisto:
– create geometric objects by using classes in the java.awt.geom package – renderthemwithGraphics2D’sdraw()and/orfill()methods
To begin we need to obtain a Graphics2D object, create a Shape object , and then draw/fill it out, e.g.
public void paintComponent (Graphics g) {
Graphics2D g2 = (Graphics2D) g; //type Casting Ellipse2D.Double eclipse = new
Ecllipse2D.Double(50, 50, 100, 100); g2.draw(eclipse);
October 1, 2021 IAT 265 51
Inner Classes for Geometric Primitives in java.awt.geom
It’s a norm for the java.awt.geom package to use static inner classes to represent shapes with different precisions
For instance, Ellipse2D is an abstract class * representing an ellipse defined by a
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com