Ben
Ben

Reputation: 57277

Java - Reusable button action handler concepts question

First off - sorry for the wall of code but it's not too horrendous, just a framework for what I'm trying to explain. It runs without errors.

The goal

I'm making a reuseable button class for my GUI and each button object needs to have a different handler when it's clicked. I want to to assign a ClickHandler object to each new button. Then, the button would call init() on the handler, and be on its way. Unfortunately, there's a typing problem, since each handler class would have a different name.

Current progress

Right now, the handler is typed as HandlerA, but I'd like to have it handle any name, like "SettingsHandler" or "GoToTheWahWah" etc.

I've tried messing about with generic types, but since I'm new to this, and from a webdev background, there seems to be a conceptual hurdle I keep knocking over. Is this the right way to approach the problem?

The code

ReuseableButton.java is a reuseable class, the only thing that changes is the action when it's clicked:

package gui;

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;

public class ReuseableButton extends JButton implements ActionListener {
  private static final long serialVersionUID = 1L;

  // I want a generic type here, not just HandlerA!
  private HandlerA ClickHandler;

  // Assemble generic button
  public ReuseableButton(Container c, String s) {
    super(s);
    addActionListener(this);
    c.add(this);
  }

  // Once again, generic type, not just HandlerA!
  public void SetClickHandler(HandlerA ch) {
    ClickHandler = ch;
  }

  // Call init() from whatever class has been defined as click handler.
  public void actionPerformed(ActionEvent e) {
    ClickHandler.init();
  }
}

Controller.java fires the frame and assembles buttons as needed (right now, only one button).

package gui;
import javax.swing.*;
import java.awt.*;

public class Controller extends JFrame {
  private static final long serialVersionUID = 1L;


  public Controller() {
    JFrame frame = new JFrame("Handler Test GUI");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        

    Container pane = frame.getContentPane();   
    pane.setLayout(new FlowLayout());

    ReuseableButton b = new ReuseableButton(pane,"Reuseable Button A");
    // THE QUESTION IS HERE: Pass a generic object?
    b.SetClickHandler(new HandlerA());

    frame.pack();
    frame.setSize(200,200);    
    frame.setVisible(true);        
  }

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

HandlerA.java is a sample of a random handler for the button click. Later, there could be HandlerB, HandlerC, etc.

package gui;

// A random handler
public class HandlerA {
  public void init() {
    System.out.println("Button clicked.");
  }
}

Thanks very much in advance!

Upvotes: 2

Views: 2197

Answers (3)

home
home

Reputation: 12538

I recommend to work with inheritence in this case:

public abstract class AbstractHandler {

    public abstract void init();
}

Then:

public class ConcreteHandlerA extends AbstractHandler {

    @Override
    public void init() {
        // do stuff...
    }

}

Controller

public class ReuseableButton extends JButton implements ActionListener {
    // I want a generic type here, not just HandlerA!
    private AbstractHandler ClickHandler;

    public Controller() {
        //...

        ReuseableButton b = new ReuseableButton(pane,"Reuseable Button A");
        AbstractHandler handlerA = new ConcreteHandlerA();
        b.SetClickHandler(handlerA);

        // ...
    }
}

Not sure if this is what you're looking for...

BTW: You can define the AbstractHandler as an interface as well, but you may want to implement some common logic here as well - shared across handlers.

Upvotes: 3

Dave
Dave

Reputation: 11162

All of you handlers should implement an interface like Clickable or something. That way the interface specifies the existence of the init function:

public interface Clickable 
{
    public void init();
}

Making the HandlerA definition:

public class HandlerA implements Clickable {
    public void init() {
       System.out.println("Button clicked.");
    }
}

Upvotes: 5

Petar Minchev
Petar Minchev

Reputation: 47383

You should use an interface for the handler.

public interface ClickHandler() {
    void init();
}

ReuseableButton b = new ReuseableButton(pane,"Reuseable Button A");
b.SetClickHandler(object which implements the ClickHandler interface);

This is the same concept as the normal JButton. There you have the ActionListener interface and the actionPerformed method in it.

P.S. If I don't understand your question, please correct me.

Upvotes: 3

Related Questions