[英]Calling a class based on the selected item in a listview in javafx
我有一個ListView,每次更改選擇時,我想調用具有該名稱的類。 例如,如果該項稱為“文本字符串”,則應調用類TextString。 我目前擁有的代碼給出了一個錯誤,說明The method insert(ArrayList<Element>) is undefined for the type Object
... Eclipse給了我一個建議將對象強制轉換為Element,但這沒有做任何事情。 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();
}
}
});
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.");
}
}
如何將對象轉換為listview選擇的任何對象?
clazz.getMethod(...)
代替clazz.getClass().getMethod(...)
objects
是ArrayList
實例,而不是List
。 你的代碼應該是下一個:
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) {
提示 我建議將insert方法中的ArrayList參數類型更改為List。 並且還只捕獲一個通用的異常,而不是一堆特定的異常。
如果您有任何進一步的問題,請告訴我。
我相信你通過嘗試使用反射來使一切變得復雜。 這是最佳的,但有時我通常只是做事更簡單。
為什么不制作一個工廠幫助程序來導入您可能需要的所有類,然后使用開關返回您需要的實例?
喜歡:
public MyInterface returnClass(String type){
switch (type){
case: "Text String":
return new TextString():
//And so on
}
}
還有另一種方法可以處理這個問題,使用HashMap
存儲所有實現,如下所示(這可以在應用程序啟動時完成,性能會更好)。
Map<String, Element> objects = new HashMap<>();
objects.put("Text String", new TextString());
並且句柄方法變成..
@Override
public void handle(MouseEvent event) {
selectedElement = (String) elementList.getSelectionModel().getSelectedItem();
// selectedElement = selectedElement.replace(" ", "");
objects.get(selectedElement).insert(Canvas.class, ArrayList.class, GraphicsContext.class);
}
由於我們沒有使用Reflection,因此這將更具可讀性和清晰度 。
你需要做的就是擁有一個帶有方法執行的接口MyElement,它將在“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 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
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.