Flippy
Flippy

Reputation: 221

Add method to TupleList

I have a TupleList with two entries and I want to add a third (like a reference to a method), my TupleList looks like:

public class NodeList<T, I> {
    public T type;
    public I id;

    public NodeList (T type, I id){
        this.type = type;
        this.id = id;
    }

    public void setT(T type){
        this.type = type;
    }
    public void setI(I id){
        this.id = id;
    }
    public T getT() { 
        return type; 
    }
    public I getI() { 
        return id; 
    }
}

And I have two Strings inside:

public static List<NodeList<String,String>> nodeList = new ArrayList<NodeList<String,String>>();

Every time I have a specific type, I want to call a related method/reference to my method. Any suggestions on how to do that? I don't want to use if or switch as I have some methods.

I create custom Nodes inside a parent AnchorPane on ButtonClick Event. All Nodes have the same Layout at the beginning, all have a Button on them and I add a unique id to every Node on creation (Buttons are created dynamically).

Now I want to link my types to different methods which will be executed when I click on the Button. For this I want to add also a reference to a function which is related to my type.

EDIT 1:

e.g.: My Button is called "RGB to Greyscale", the String type of my Node is rgbgrey. When I click on the Button I create a Node (just a draggable AnchorPane with a Button on it and a Label on top with the String of my type). I have a Button event, where I want to execute different methods, depending on the Buttons I clicked to create my Nodes. Therefore I create a List with different entries. After creating my Node I add a unique String id and set the String type name to rgbgrey. Now I want to call the method rgbtogrey(); when I click on my Node Button.

Another Button is called "Rotate Image", the String type is now rotimg. The layout of my Node is completely the same. When I click now on the Button on my Node, I want to execute a different function in my Button event and call the method rotateimg();.

I create the Nodes like this inside my Node class:

void addRotateNode(ActionEvent event){
    Node nde = new Node();

    id = nde.getId();
    type = new String("rotimg");
    nodeList.add(new NodeList<String, String>(type, id)); //add id and type to list
    nde.nodeLayout(); // This is where I set my Layout
    //...
}

Right now I try this, but I want to avoid switch, because I'll add many more functions.

@Override
public void handle(MouseEvent event) {
    for(int i = 0; i <= ViewController.nodeList.size(); i++){
        String func = ViewController.nodeList.get(i).getT();
            switch(func){
            case "rgbgray":
                //rgbtogrey();
                break;
            case "rotimg":
                //rotateimg();
                break;
        }   
    }
}});

I have a custom EventHandler class:

public class ActionEventHandler implements EventHandler<ActionEvent> {

    private final EventHandler<ActionEvent> eventHandler;
    private final String name;

    public ActionEventHandler(String name, EventHandler<ActionEvent> eventHandler) {
        Objects.requireNonNull(name);
        Objects.requireNonNull(eventHandler);
        this.name = name;
        this.eventHandler = eventHandler;
    }

    @Override
    public String toString() {
        return name;
    }

    @Override
    public void handle(ActionEvent event) {
        eventHandler.handle(event);
    }

}

EDIT 2:

I changed my List to:

public static List<NodeList<String,String, EventHandler<ActionEvent>>> nodeList = new ArrayList<NodeList<String,String, EventHandler<ActionEvent>>>();

and I modified my Node creation to:

void addRotateNode(ActionEvent event){
    Node nde = new Node();

    id = nde.getId();
    type = new String("rotimg");
    EventHandler<ActionEvent> handler = new ActionEventHandler(type, this::rotimg);
    nodeList.add(new NodeList<String, String, EventHandler<ActionEvent>>(type, id, handler));
    nde.nodeLayout(); // This is where I set my Layout
    //...
}

Upvotes: 0

Views: 83

Answers (1)

AxelH
AxelH

Reputation: 14572

From what I have understood, you should use a pattern, the Command pattern. Since we can't pass a method's reference like C (or other), this pattern is a the one to use to fixed this problem.

This is basicly an Interface

interface Command {
    void execute(); //Could take parameter, return something, your choice.
}

For each "function", we will implements a version of Command. From this instance, we have a sort of reference that can call a method.

Then, you can store any implementation of this interface into a Collection.

Just a simple example :

List<Command> list = new ArrayList<>();
list.add(new ForwardCommand()); //An implementation of the interface
list.add(new RecordCommand());  //An other one
list.add(new ClearCommand());   //An other one

And you just need to get on of those instance an call the interface method to execute the function.

Command c = list.get(0); //Get forwarCommand
c.execute(); //That will execute the functionnality of the instance selected

Note : This could be done using Reflexion but I found that cleaner an more maintainable. (and less risky)

Upvotes: 1

Related Questions