Reputation: 221
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
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