Calling a class based on the selected item in a list in javafx

I have a ListView, and every time the selection is changed, I want to call a class with this name. For example, if an element is called a "Text String", then the TextString class must be called. The code I have gives me an error saying The method insert(ArrayList<Element>) is undefined for the type Object ... Eclipse gives me a suggestion to pass the object as an Element, but it does nothing. The Element class is a superclass, and TextString will implement this class.

Here is the code that I still have:

  elementList.itemsProperty().bind(listProperty); listProperty.set(FXCollections.observableArrayList(elementListItems)); elementList.setOnMouseClicked(new EventHandler<MouseEvent>() { public String selectedElement = "Text String"; @Override public void handle(MouseEvent event) { selectedElement = (String)elementList.getSelectionModel().getSelectedItem(); selectedElement = selectedElement.replace(" ", ""); Class<?> clazz; try { clazz = Class.forName("elements."+selectedElement); Constructor<?> ctor = clazz.getConstructor(); Object object = ctor.newInstance(); Method meth = clazz.getClass().getMethod("insert", new Class<?>[] { Canvas.class, ArrayList.class, GraphicsContext.class }); meth.invoke(object, canvas, objects, gc); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }); 

Element.java

  public abstract class Element { public String name; public String description; public Canvas canvas; public ArrayList<Element> objects; public GraphicsContext gc; void remove(){ } void toggle(){ } void setBounds(int x, int y, int w, int h){ } public abstract void insert(Canvas canvas, ArrayList<Element> objects, GraphicsContext gc); } 

TextString.java

  public class TextString extends Element { private GraphicsContext gc; TextString() { super(); this.name = "Text String"; this.description = "A literal readable string of text."; } @Override public void insert(Canvas canvas, ArrayList<Element> objects, GraphicsContext gc) { this.gc = gc; this.canvas = canvas; this.objects = objects; System.out.println("Text string created."); } } 

How can I pass an object to any object selected in the list?

+5
source share
4 answers
  • You must use explicit casting.
  • Use clazz.getMethod(...) instead of clazz.getClass().getMethod(...)
  • Watchout objects will be an ArrayList instance, not a List .

Your code should look like this:

  try { clazz = Class.forName("elements."+selectedElement); Constructor<?> ctor = clazz.getConstructor(); Element object = (Element) ctor.newInstance(); Method meth = clazz.getMethod("insert", new Class<?>[] { Canvas.class, ArrayList.class, GraphicsContext.class }); meth.invoke(object, canvas, objects, gc); } catch (ClassNotFoundException e) { 

Tip . I would suggest changing the type of the ArrayList parameter in the insert method for List. And also catch only one general exception, not a bunch of certain.

Let me know if you have any additional problems.

+4
source

I believe that you are all complicating everything by trying to use reflection. This is optimal, but sometimes I usually just make things simpler.

Why don't you create a factory helper that imports all the classes you might need, and then use the switch to return the instance you want?

how

 public MyInterface returnClass(String type){ switch (type){ case: "Text String": return new TextString(): //And so on } } 
0
source

There is another way to handle this, use HashMap to store all implementations as follows (this can be done when your application is running, performance will be better).

 Map<String, Element> objects = new HashMap<>(); objects.put("Text String", new TextString()); 

And the descriptor method becomes ..

 @Override public void handle(MouseEvent event) { selectedElement = (String) elementList.getSelectionModel().getSelectedItem(); // selectedElement = selectedElement.replace(" ", ""); objects.get(selectedElement).insert(Canvas.class, ArrayList.class, GraphicsContext.class); } 

It will be more readable and clean, since we do not use Reflections.

0
source

What you need to do is just have a MyElement interface with a method execution. Implementing them will call everything you need in "execute ()"

Basically, I propose a command template that is the basis for all user interface operations when doing BE

my 2 cents, an example of implementation from my old project

  CommandFactory factory = CommandFactory.getInstance(); Command command = factory.createCommand(relativeURL); if(command != null){ command.execute( /* Object */ input); } } 

in factory

 /** * Factory for commands * * @author andre */ public class CommandFactory { // singleton instance protected static CommandFactory instance = new CommandFactory(); //cache of objects Map<String, Command> cache = new HashMap<>(); // protected constructor prevents creating object outside protected CommandFactory(){ } // return signleton instance of factory public static CommandFactory getInstance(){ return instance; } /** * create and return appropriate command * * @return found command * @throws exception if something bad happened */ public Command createCommand(String classname){ try { Command com = cache.get(URL); if(com == null){ Command temp = (Command) Class.forName(classname).newInstance(); if(temp != null){ cache.put(URL, temp); com = cache.get(URL); } } return com; } catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException ex) { Logger.getLogger(getClass().getName()).error(ex); return new Error404(); } } } 

to interface

 public interface Command{ void execute(Object input); } 

and implementation example

 public class EditUserInfo implements Command { @Override public void execute(Object object) { callWhatever((String) object); } private void callWhatever(String textFromField){ // inner logic example } } 
0
source

Source: https://habr.com/ru/post/1273141/


All Articles