Difference between revisions of "CSC212 Lab 15 2014"

From dftwiki3
Jump to: navigation, search
(GUI Elements)
Line 140: Line 140:
  
 
</source>
 
</source>
 +
* Add a new ''member variable'' (field) to the '''viewer''', called '''button1''', of type '''Button'''.
 +
* Initialize '''button1''' in the  setup() method:
 +
<br />
 +
:::<source lang="java">
 +
//--- create the button ---
 +
button1 = new Button( this, 10, HEIGHT-25, "Show components" );
 +
</source>
 +
<br />
 +
* Redraw the button in the draw() method, right after the call to background(), which erases the whole screen:
 +
:::<source lang="java" highlight="4,5">
 +
// erase window, make background white
 +
background( 255, 255, 255 );
 +
 +
// draw button
 +
button1.draw();
 +
</source>
 +
<br />

Revision as of 17:08, 27 November 2014

--D. Thiebaut (talk) 09:43, 27 November 2014 (EST)


This lab introduces the Model-View-Controller (MVC) system for implementing Graphical User Interfaces (GUI). Please review the slides from the MVC lecture notes if necessary.


First Contact

50x50Network.png


  • Create a new project, or add new files to an existing project. You will need to import core.jar from the Processing 2 app into your project, and then add it to the build path.
  • You need to create 3 different classes, one for the controller, one for the viewer, and one for the model.
  • MVC1_controller.java
  • MVC1_viewer.java
  • MVC1_model.java
  • This tutorial contains the code for all three classes. Copy/paste the code into your three classes.


Run the Applet


  • The starting class is the viewer. It's the applet class.
  • Run it. Play with the applet to understand how it works.


Explore the Code


The Model


  • Read the code for the model. Notice that it contains the bare definition of a graph, its vertices, and its edges, and not much else. That's what a model should contain.
  • Look at the main public methods. They are few. They mostly allow one to
  • initialize a graph, if we want one already made.
  • add an edge
  • get the dimension of the grid
  • get the adjacency list of a vertex


Modification 1
Change the probability100 variable; it controls the probability of creating an edge between a vertex and its neighbors. Its value should range between 0 and 100. The lower the value, the less connected the graph is. The closest to 100, the more fully interconnected the vertices get. Run the applet again to see how connected or disconnected your grid becomes.


Modification 2
Change the maxNoVerticesRows and maxNoVerticesCols which define the number of rows and columns of the grid to something different. Say 40, 60. Or 60, 100. Notice that the visualization will match the new geometry.


The Controller


  • Read the code of the controller.
  • Notice that the most important action it performs is to set up relationships between the three components, controller, model, and viewer. This way the viewer can call methods of the controller or model, if needed, and similarly for the other two.
  • the setVertexUnderMouse() method is a call-back method called by the viewer whenever the mouse is over a vertex. It is a way for the controller to be made aware (by the viewer) that the mouse pointer is over a vertex, and to make something happen. In this case, the controller instructs the viewer to display the vertex number next to the mouse pointer, and to display its adjacency list at the bottom of the applet. The viewer should not really be the one deciding what to do. The controller is the one that should decide.


The Viewer


  • Read the code of the viewer. It is the most complex of the three.
  • It is the main entry point of the application. That's the class that starts it all.
  • The two important methods are:
  • setup(): it is called first, once. Its purpose is to
  • start the controller first. The controller will get the model to setup the graph, with its geometry.
  • the controller gets the model to initialize the graph
  • the geometry of the applet is setup so that it will match the grid structure of the graph
  • draw(): it is called repeatedly, over and over, about 30 times a second. This is what inheriting from the PApplet class does for us, automatically.
  • The other methods are used to relate vertices to locations on the canvas of the applet, or to figure out if the mouse is over a vertex.


Modification 3
Add a new method to the viewer:
        public void drawCircles( int vertexNo ) {
		int[] xy = getXY( vertexNo, model.getNoRows(), model.getNoCols() );
		int radius = frameCount % 15;
		ellipse( xy[0], xy[1], 2*radius, 2*radius );
	}
This method draws circles around the vertex passed as an argument. The radius of the circles changes with time.
The field frameCount is part of the PApplet class. It is incremented automatically every time the draw(0 method is called. So frameCount % 15 goes 0, 1, 2, 3,...14, 0, 1, 2, 3, 4... 14 in one seconds (since draw() is called 30 times a second. Drawing a circle whose radius goes from 0 to 14 twice in a second will make for some interesting animation.
Make the controller call this new method every time the mouse is over a vertex.
You should see some animation going on every time your mouse pointer is over a vertex.


GUI Elements


  • Let's ask a (very) simple, "home-made" button to the viewer.
  • Create a new class called Button.java in your project.
import processing.core.PApplet;

/**
 * A simple class for implementing a square button box.  If the button
 * is clicked, a cross is drawn in the button, otherwise it is 
 * left empty.
 * The button has a status, depending on the last time it was clicked
 * by the mouse.  Every time it is clicked, it switches state.
 */
public class Button {
	private PApplet parent;	// link to applet, so the button can display itself
	private int x;			// x,y coordinates of top left corner
	private int y;
	private int w;			// width (default 20)
	private int h;			// height (default 20)
	boolean ONOFF;			// true = ON, false = OFF
	String caption;			// the text next to the button
	
	/**
	 * constructor
	 * @param p a reference to the PApplet, so that it can 
	 * @param xx the x coordinate of the top-left corner
	 * @param yy the y coordinate of the top-left corner
	 * @param s  the name to print next to the button
	 */
	Button( PApplet p, int xx, int yy, String s ) {
		parent  = p;
		x 		= xx;
		y 		= yy;
		w 		= 20;
		h 		= 20;
		ONOFF 	= false;
		caption = s;
	}
	
	public void setONOFF( boolean b ) 	{ ONOFF = b; 		}
	public boolean isON( ) 				{ return ONOFF; 	}
	public boolean isOFF( )				{ return !ONOFF; 	}
	public void switchState() 			{ ONOFF = ! ONOFF;  }
	
	/**
	 * draw the button on the applet.
	 */
	public void draw() {
		parent.fill( 255, 255, 255 );		// white background
		parent.stroke( 0, 0, 0 );			// black outline
		parent.strokeWeight( 2 );			// line width
		parent.rect( x, y, w, h );
		if ( ONOFF ) {
			parent.line( x,  y,  x+w,  y+h );
			parent.line( x+w, y, x, y+h );
		}
		parent.fill( 0, 0, 0 ); 			// black text
		parent.textAlign( parent.LEFT );
		parent.text( caption, x + w + 5, y + h/2 );
	}
	
	public boolean containsMouse() {
		return ( parent.mouseX >= x && parent.mouseX <= x+w 
				&& parent.mouseY >= y && parent.mouseY <= y+h );
	}
}
  • Add a new member variable (field) to the viewer, called button1, of type Button.
  • Initialize button1 in the setup() method:


		//--- create the button ---
		button1 = new Button( this, 10, HEIGHT-25, "Show components" );


  • Redraw the button in the draw() method, right after the call to background(), which erases the whole screen:
		// erase window, make background white
		background( 255, 255, 255 );
				
		// draw button
		button1.draw();