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