javafx

2017-11-06 138 views
5

'da bir liste görünümünde seçilen öğeye göre bir sınıf aramak ListView'im var ve seçim her değiştiğinde, o isimle bir sınıfı çağırmak istiyorum. Örneğin, öğeye "Metin Dizesi" denirse, TextString sınıfı çağrılmalıdır. Şu anda sahip olduğum kod bana The method insert(ArrayList<Element>) is undefined for the type Object diyerek bir hata veriyor ... Eclipse bana nesneyi Element olarak yayınlamak için bir öneri veriyor, ancak bu hiçbir şey yapmıyor. Öğe sınıfı bir üst sınıftır ve TextString bu sınıfı uygular. İşte javafx

var bugüne kadar kodudur:

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 yapabilirim ne olursa olsun nesne nesneyi döküm nasıl

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."); 
    } 

} 

liste görünümünde seçiliyor mu?

+1

daha iyi olacağını farklı örneklerini oluşturur basitçe anahtar sağlanan dizgeye bağlı sınıflar. – FilipRistic

+0

Eh, sonunda benim app uzatılabilir hale getirmeyi umuyoruz ... anlam kullanıcıların yerel bir AppData klasörüne özel eleman sınıfları eklemek için izin. Anahtar ifadeleri kullanmak buna izin vermez. Artı ben app ile dahil birçok farklı unsurları üzerinde yapmayı planlıyoruz ve bu cehennem gibi dağınık olurdu. – ShoeLace1291

+0

Bu hatayı tam olarak nereden alıyorsunuz? Insert() 'için açık bir çağrı göremiyorum. – shmosel

cevap

4
  1. Açık döküm kullanmanız gerekir.
  2. Kullanım clazz.getMethod(...) yerine clazz.getClass().getMethod(...)
  3. Watchout objectsArrayList örneği değil List olmak.

Kodunuz gelecek etmeliyim:

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) { 

İpucu. Ekle yönteminde ArrayList parametresinin türünü Listele olarak değiştirmenizi öneririm. Ayrıca, belirli bir grup yerine yalnızca bir genel Özel Durum yakalamak için. Bununla ilgili başka bir sorun olursa lütfen bildirin.

+0

Şimdi java.lang.NoSuchMethodException: elements.TextString diyerek bir hata alıyorum. () – ShoeLace1291

+0

'TextString'in çalışması için clazz.getConstructor()' için varsayılan kurucu ('TextString()') gerekir. – JimmyB

+0

Varsayılan bir kurucu var. OP'mdeki son kod bloğuna bakın. – ShoeLace1291

0

Yansımayı kullanmaya çalışarak her şeyi zorlaştırdığınıza inanıyorum. Optimaltir, ancak bazen sadece işleri basitleştiririm.

Neden ihtiyaç duyabileceğiniz tüm sınıfları içe aktaracağınız bir fabrika yardımcısı yapmıyorsunuz ve daha sonra ihtiyacınız olan örneği döndürmek için bir anahtar kullanmıyorsunuz?

gibisin: aşağıdaki gibi tüm uygulamaları saklamak için bir HashMap kullanmak bu işleyebilir başka yolu yoktur

public MyInterface returnClass(String type){ 

    switch (type){ 

    case: "Text String": 
    return new TextString(): 

//And so on 

} 

} 
0

(bu yapılabilir Başvurunuz başlatıldığında, performans daha iyi olacaktır).

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

Ve sap yöntemi haline gelir ..

@Override 
public void handle(MouseEvent event) { 
    selectedElement = (String) elementList.getSelectionModel().getSelectedItem(); 
//  selectedElement = selectedElement.replace(" ", ""); 

    objects.get(selectedElement).insert(Canvas.class, ArrayList.class, GraphicsContext.class); 

} 

biz Yansımalar kullanmıyorsanız bu durum daha okunaklı ve temiz olacaktır.Eğer bunlardan içinde gereken neyse arayacak Uygulama yürütmek basitçe yöntemle bir arayüz MyElement var yapmanız gereken şey

0

"yürütme()"

temelde tüm temelidir komut desen önermek yapıyor UI işlemleri fabrikaya

içine benim eski süren projenin

den

benim 2 sent, implemntation örnek BE Eğer zaten muhtemelen daha sonra yaptığımız ne teklif sınıflar biliyorsanız arayüzüne

public interface Command{ 

void execute(Object input); 
} 

ve uygulama örneği haline

/** 
* 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 
} 



}