6.09.3 Properly with Java Interfaces

Custom Canvas -> Application using Interfaces

The previous example works very well; however, there is one major flaw. If we want to re-use our custom canvas in another application called DrawingApp then we can't without changing the code, as it requires an application called CanvasApplication to be passed. Clearly we need a way to allow the name of the calling class to change or our code will not be very portable.

To do this, we use Java Interfaces. We saw Java Interfaces before, but what they allow us to do here is to abstract the calling application to "any application that implements our Java interface"


Figure X. Canvas Mouse Application with Interfaces

So, here is our Java interface. At the moment there is only one method that we allow our custom canvas to call on the main application and we'll rename it slightly to setNumber(int). So, this interface below states that if any class implements the CounterField interface then it must write the code for a method called setNumber. So, our class can have any name!

12345
package ee402;

public interface CounterField {
        public void setNumber(int number);
}

So, here is the application implementing the CounterField interface. Without reading past the "public class CanvasApplication..." line, I know that there must be a setNumber(int) method, otherwise the code could not compile. 

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
package ee402;

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

@SuppressWarnings("serial")
public class CanvasApplicationInterfaces extends Frame implements WindowListener, ItemListener, CounterField{
        
        private CustomCanvasInterfaces canvas;
        private Choice colorChoice;
        private TextField numberCircles;
        
        public CanvasApplicationInterfaces(){
                super("Canvas Mouse Intefaces");
                this.canvas = new CustomCanvasInterfaces(this, 250,250);
                this.add(canvas, BorderLayout.CENTER);
                
                Panel south = new Panel(new FlowLayout());
                numberCircles = new TextField(10);
                numberCircles.setEditable(false);
                this.setNumber(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 setNumber(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 CanvasApplicationInterfaces();
        }
}

We pass the object of CanvasApplicationInterfaces directly to the constructor of the custom canvas class and it looks like the same as before; however, there is one major difference, which can be seen below - The custom canvas does not expect an object of CanvasApplicationInterfaces, it expects an object of the interface CounterField (see the constructor). 

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
package ee402;

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

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

        int width, height;
        Color drawColor = Color.red;
        Vector<Point> points = new Vector<Point>(10);
        static int radius = 10;
        CounterField callingApp;
        
        public CustomCanvasInterfaces(CounterField 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.setNumber(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) {}
}

This means that any class that has implemented the CounterField interface can call the constructor above as it must have the required setNumber() method that is called in the paint() method above.

This is good programming practice as this one Custom Canvas class can be used by many different calling applications, even within the same project.


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.
ċ
CanvasApplicationInterfaces.java
(2k)
Derek Molloy,
26 Nov 2013, 07:22
ċ
CounterField.java
(0k)
Derek Molloy,
26 Nov 2013, 07:22
ċ
CustomCanvasInterfaces.java
(1k)
Derek Molloy,
26 Nov 2013, 07:22
Comments