基于javafx中listview中的选定项调用类

基于javafx中listview中的选定项调用类,java,javafx-8,Java,Javafx 8,我有一个ListView,每次更改选择时,我都想用该名称调用一个类。例如,如果项目名为“文本字符串”,则应调用类TextString。我当前拥有的代码给了我一个错误,说明类型对象的插入方法(ArrayList)未定义。。。Eclipse给了我一个将对象强制转换为元素的建议,但这没有任何作用。Element类是一个超类,TextString将实现该类 以下是我目前掌握的代码: elementList.itemsProperty().bind(listProperty); li

我有一个ListView,每次更改选择时,我都想用该名称调用一个类。例如,如果项目名为“文本字符串”,则应调用类TextString。我当前拥有的代码给了我一个错误,说明类型对象的插入方法(ArrayList)未定义。。。Eclipse给了我一个将对象强制转换为元素的建议,但这没有任何作用。Element类是一个超类,TextString将实现该类

以下是我目前掌握的代码:

   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();
                }
            }
        });
elementList.itemsProperty().bind(listProperty);
set(FXCollections.observableAryList(elementListItems));
elementList.setOnMouseClicked(新的EventHandler(){
公共字符串selectedElement=“Text String”;
@凌驾
公共无效句柄(MouseeEvent事件){
selectedElement=(字符串)elementList.getSelectionModel().getSelectedItem();
selectedElement=selectedElement.replace(“,”);
课堂讨论;
试一试{
clazz=Class.forName(“元素”+selectedElement);
Constructor=clazz.getConstructor();
Object=ctor.newInstance();
方法meth=clazz.getClass().getMethod(“插入”,新类[]{Canvas.Class,ArrayList.Class,GraphicsContext.Class});
方法调用(对象、画布、对象、gc);
}catch(classnotfounde异常){
e、 printStackTrace();
}捕获(无此方法例外){
e、 printStackTrace();
}捕获(安全异常e){
e、 printStackTrace();
}捕获(实例化异常e){
e、 printStackTrace();
}捕获(非法访问例外e){
e、 printStackTrace();
}捕获(IllegalArgumentException e){
e、 printStackTrace();
}捕获(调用TargetException 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);
}
公共抽象类元素{
公共字符串名称;
公共字符串描述;
公共画布;
公共ArrayList对象;
公共图形上下文gc;
作废删除(){
}
void toggle(){
}
无效收进边界(整数x,整数y,整数w,整数h){
}
公共抽象void insert(画布、ArrayList对象、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.");
    }

}
公共类TextString扩展元素{
私有图形上下文gc;
TextString(){
超级();
this.name=“Text String”;
this.description=“文字可读字符串。”;
}
@凌驾
公共void插入(画布、ArrayList对象、GraphicsContext gc){
this.gc=gc;
this.canvas=画布;
this.objects=对象;
System.out.println(“创建的文本字符串”);
}
}
如何将对象强制转换为listview正在选择的任何对象

  • 您应该使用显式转换
  • 使用
    clazz.getMethod(…)
    而不是
    clazz.getClass().getMethod(…)
  • 监视
    对象
    成为
    数组列表
    实例,而不是
    列表
  • 您的代码应该如下所示:

     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) {
    
    试试看{
    clazz=Class.forName(“元素”+selectedElement);
    Constructor=clazz.getConstructor();
    元素对象=(元素)ctor.newInstance();
    方法meth=clazz.getMethod(“插入”,新类[]{Canvas.Class,ArrayList.Class,GraphicsContext.Class});
    方法调用(对象、画布、对象、gc);
    }catch(classnotfounde异常){
    
    提示。 我建议将insert方法中ArrayList参数的类型更改为List。 并且只捕获一个泛型异常,而不是一堆特定的异常


    如果您有任何进一步的问题,请告诉我。

    我相信您尝试使用反射会使一切变得过于复杂。反射是最佳的,但有时我宁愿做更简单的事情

    为什么不制作一个factory helper来导入您可能需要的所有类,然后使用开关返回您需要的实例

    比如:


    还有另一种处理方法,使用
    HashMap
    存储所有实现,如下所示(这可以在应用程序启动时完成,性能会更好)


    这将更具可读性和清晰性,因为我们不使用反射。

    您需要做的只是拥有一个接口MyElement 使用方法execute 它的实现将调用“execute()”中所需的任何内容

    基本上,我建议使用命令模式,这是执行BE时所有UI操作的基础

    我的2美分,来自我的旧项目的实施示例

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

    /**
     * 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();
        }
    }
    
    
    }
    
    以及实现示例

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

    如果您已经知道您可能提供的类,那么最好简单地放置switch,它根据提供的字符串创建不同类的实例。我希望最终使我的应用程序可扩展…这意味着允许用户将自定义元素类添加到本地AppData文件夹。使用switch语句不允许这样。另外,我计划在应用程序中包含许多不同的元素,这会非常混乱。你到底从哪里得到错误?我没有看到任何对
    insert()
    的显式调用。错误发生在调用.getConstructor()方法的行上。另外,我使用meth.invoke()调用insert()方法这将是一个运行时错误,Eclipse不会给出建议
        CommandFactory factory = CommandFactory.getInstance();
        Command command = factory.createCommand(relativeURL);
        if(command != null){
            command.execute( /* Object */ input);
        }
    }
    
    /**
     * 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();
        }
    }
    
    
    }
    
    public interface Command{
    
    void execute(Object input);
    }
    
    public class EditUserInfo implements Command {
    
    @Override
    public void execute(Object object) {
         callWhatever((String) object);
        }
    
    private void callWhatever(String textFromField){
    // inner logic example
    }
    
    
    
    }