So here's the rundown. I have a base class, I want to put a clickHandler in it because all of my subclasses will need it, but they will all execute different code when it is triggered. My question is, how can i have a clickHandler in my base class and when it is triggered, it can execute specific code from the subclass?

my code is long and complicating, so ill give an example.

Base Class

public class CountProgram extends Canvas {
public CountProgram(){
        super();
        init();
    }
private void init() {
currGrid.addCellClickHandler(new CellClickHandler() {
                        public void onCellClick(CellClickEvent event) {
                            //here is where i want to call subclass code to execute

                          
                        }
                    });
                }

            }

subclass:

public class stHrTeacherCount extends CountProgram {
 public stHrTeacherCount(StaffMain sm,String permission){
        super();
        _sm=sm;
        setPermission(permission);
      
    }
public void executeCode() {
//here would be the code i want to execute when the event is triggered
}

}

Ive tried some things, like setting variables from "executeCode()" to variables in the super class, but it was messy and i was unable to get it to work successfully. Would be nice if I could just pass a method as a parameter, but unfortunately you can in Java and I dont know an alternative. hope i explained well enough, Thanks!

Recommended Answers

All 4 Replies

Create an interface called ClickHandler. Have all of your classes (that you want to execute code when the thing is clicked) implement the ClickHandler interface. The ClickHandler interface should have one method called handleClick(). Each of your classes can provide their own implementation of handleClick(). Now, in your base class, you can keep an ArrayList of Objects that want to be notified when a click happens. You can then loop through the ArrayList and for each Object in the ArrayList, call the handleClick() method.

edit:
Here is an example of what I am talking about. You can actually credit one of our mods, Ezzaral, with coming up with this example (he gave it to me as advice a year or so ago, I think it might clarify things for you).

import java.util.ArrayList;
import java.util.List;

public class mainTest {

    public static void main(String[] args) {
        Model model = new Model();
        View view = new View();

        /** add the view as a listener */
        model.addListener(view);

        /** do something to the model */
        model.updateSomething();
    }
}

class Model {
    /** list of interested listeners (observers, same thing) */
    List<ModelListener> listeners = new ArrayList<ModelListener>();

    /** add a new ModelListener observer for this Model */
    public void addListener(ModelListener listener) {
        listeners.add(listener);
    }

    /** called internally when you need to tell the observer stuff changed */
    private void fireStuffChanged() {
        for (ModelListener listener : listeners) {
            listener.stuffChanged();
        }
    }

    /** method that results in a change in the model */
    public void updateSomething() {
        // do whatever
        System.out.println("Model: I'm changin stuff in here...");
        // notify observers
        fireStuffChanged();
    }
}

/** interface for the listeners/observers callback method */
interface ModelListener {

    void stuffChanged();
}

class View implements ModelListener {

    public void stuffChanged() {
        System.out.println("View: Oh, something changed. I better show the new stuff!");
    }
}
commented: Ezzaral had just taught me a bit of this and your comments helped me understand better what is going on, thanks bud. +1

Thank you for the reply, I havent used interface much but from your example I see how it works and it would be good for me to practice. Also, I believe I explained it wrong, but I do not want to call all of the subclass's handleClick methods but rather, only the one that was instantiated. Either way, I appreciate your help and am sure I can create a solution with your advice. Thanks again :)

It will only call the handleClick() method of the Object that was instantiated. I think it does what you are talking about - go try it out and let me know.

If your base class has an executeCode() method, then you should be able to call that just fine in your handler. Your subclasses can override it however they wish. Example:

import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

public class ClickSubclass extends javax.swing.JFrame {

    public ClickSubclass() {
        initComponents();
        add(new LabelA());
        add(new LabelB());
        pack();
    }

    /** base class with mouse handler and a doClickStuff method */
    class LabelA extends JLabel {
        public LabelA(){
            setText("A");
            setPreferredSize(new Dimension(30,30));
            addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    doClickStuff();
                }
            });
        }

        public void doClickStuff(){
            JOptionPane.showMessageDialog(this, "Clicked a LabelA thing");
        }
    }

    /** extends base class and does different "stuff" in doClickStuff method */
    class LabelB extends LabelA{
        public LabelB(){
            super();
            setText("B");
        }

        public void doClickStuff(){
            JOptionPane.showMessageDialog(this, "Clicked a LabelB thing");
        }
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(new java.awt.FlowLayout());

        pack();
    }// </editor-fold>

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ClickSubclass().setVisible(true);
            }
        });
    }

}

That all should work fine if the things you want to work with are subclasses of that base. If they aren't, you'll need a separate interface like BJSC mentioned above.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.