6.09.2 Canvas Application with Callback

Custom Canvas -> Application

So, we have written code to allow our application to modify the state/properties of the custom canvas by calling its methods. The question now is how do we do it the other way? In our application, every time you press the button you create a new circle -- what if we wanted to tell the application how many circles had been created? This is a form of callback, as the application has no idea when a new circle will be created, so we need to pass that information from the custom canvas back to the application.

In the figure below you can see the number of circles displayed in the read-only TextField.

Figure X. Canvas Application with Callback

The application needs to be modified slightly as we now need to pass a reference of the application to the custom canvas. You can see that below - when we create the custom canvas we use this.canvas = new CustomCanvasCallback(this, 250, 250); so we are passing a reference to this object (the application) to the constructor of the CustomCanvas, which has been modified to receive the reference. 

We also add a new method in the application called setNumberCircles(int) that allows us to pass the message from the custom canvas to the application. This method simply places the the number in the TextField object called numberCircles.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
package ee402;

import java.awt.*;
import java.awt.event.*;

@SuppressWarnings("serial")
public class CanvasApplicationCallback extends Frame implements WindowListener, ItemListener{
        
        private CustomCanvasCallback canvas;
        private Choice colorChoice;
        private TextField numberCircles;
        
        public CanvasApplicationCallback(){
                super("Canvas Mouse Application");
                this.canvas = new CustomCanvasCallback(this, 250,250);
                this.add(canvas, BorderLayout.CENTER);
                
                Panel south = new Panel(new FlowLayout());
                numberCircles = new TextField(10);
                numberCircles.setEditable(false);
                this.setNumberCircles(0);
                south.add(numberCircles);
                colorChoice = new Choice();
                colorChoice.addItem("Red");
                colorChoice.addItem("Green");
                colorChoice.addItem("Blue");
                south.add(colorChoice);
                colorChoice.addItemListener(this);
                this.add(south, BorderLayout.SOUTH);
                
                
                this.addWindowListener(this);
                this.pack();
                this.setVisible(true);
        }
        
        public void setNumberCircles(int number){
                this.numberCircles.setText("Number:" + number);
        }
        
        public void itemStateChanged(ItemEvent e) {
                if (e.getItem().equals("Red")) canvas.setColor(Color.red);
                else if (e.getItem().equals("Green")) canvas.setColor(Color.green);
                else canvas.setColor(Color.blue);
        }

        public void windowActivated(WindowEvent arg0) {}
        public void windowClosed(WindowEvent arg0) {}
        public void windowClosing(WindowEvent arg0) { System.exit(0); }
        public void windowDeactivated(WindowEvent arg0) {}
        public void windowDeiconified(WindowEvent arg0) {}
        public void windowIconified(WindowEvent arg0) {}
        public void windowOpened(WindowEvent arg0) {}

        public static void main(String[] args) {
                new CanvasApplicationCallback();
        }
}

The custom canvas object has been modified below to now receive a reference to the calling application in the constructor, so you can see "CanvasApplicationCallback app" being passed to the canvas object. Now that we have this reference (called callingApp), we are now able to call the setNumberCircles(int) method. So, when we redraw the canvas we can send a message back to the application to tell it to update the text in the TextField (even if it doesn't need to be updated).

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
package ee402;

import java.awt.*;
import java.awt.event.*;
import java.util.*;

@SuppressWarnings("serial")
public class CustomCanvasCallback extends Canvas implements MouseListener{

        int width, height;
        Color drawColor = Color.red;
        Vector<Point> points = new Vector<Point>(10);
        static int radius = 10;
        CanvasApplicationCallback callingApp;
        
        public CustomCanvasCallback(CanvasApplicationCallback app, int width, int height){
                this.setSize(width,height);
                this.width = width;
                this.height = height;
                this.addMouseListener(this);
                this.callingApp = app;
                this.repaint();
        }
                
        public void paint(Graphics g){
                g.setColor(drawColor);
                for(int i=0; i<points.size(); i++){
                        Point p = points.elementAt(i);
                        g.drawOval(p.x, p.y, 2*radius, 2*radius);
                }
                this.callingApp.setNumberCircles(points.size());
        }
        
        public void setColor(Color c){
                drawColor = c;
                this.repaint();
        }

        public void mouseClicked(MouseEvent e) {
                points.addElement(new Point(e.getX()-radius, e.getY()-radius));
                this.repaint();
        }
        public void mouseEntered(MouseEvent e) {}
        public void mouseExited(MouseEvent e) {}
        public void mousePressed(MouseEvent e) {}
        public void mouseReleased(MouseEvent e) {}
}


These notes are copyright Dr. Derek Molloy, School of Electronic Engineering, Dublin City University, Ireland 2013-present. Please contact him directly before reproducing any of the content in any way.
ċ
CanvasApplicationCallback.java
(2k)
Derek Molloy,
26 Nov 2013, 07:12
ċ
CustomCanvasCallback.java
(1k)
Derek Molloy,
26 Nov 2013, 07:12
Comments