2011-02-23 149 views
0

嗨,我目前正在做我的最後一年的項目;我需要開發算法可視化工具。我需要迎合用戶定義的算法;這是用戶在我的工具中提供的文本編輯器中鍵入的算法的動畫。Java反射問題

我正在使用Java編譯器API編譯用戶鍵入並保存的代碼。我的工具提供了一組用戶可以在他/她的算法中使用的類。

例如:

myArray的(這個類是通過我的工具提供)

import java.awt.*; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.accessibility.AccessibleContext; 
import javax.swing.*; 
public class myArray extends JComponent { 

int size = 0; 
int count = 0; 
int[]hold; 
Thread th; 



public myArray(int[]arr)//pass user array as parameter 
{ 
    //th = new Thread(); 

    size=arr.length; 
    hold = arr;//make a copy of the array so as to use later in swap operation 

} 

public int length() 
{ 
     return hold.length; 
} 


public void setAccessibleContext(AccessibleContext accessibleContext) { 
    this.accessibleContext = accessibleContext; 
} 


public void paintComponent(Graphics g) 
{ 
    super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g; 
      this.setPreferredSize(new Dimension(360,100)); 
    for(int i=1; i<=size; i++) 
    { 
     g2d.drawRect((i*30), 30, 30, 50); 
    } 

    for(int i=1; i<=size; i++) 
    { 
     g2d.drawString(Integer.toString(hold[i-1]), (i*30)+15, 30+25); 
    } 
} 






public void set(int i, int j)//position of the two elements to swap in the array 
{ 
    try { 
     th.sleep(2000);//sleep before swapping because else user won't see original array since it would swap and then sleep 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    int temp = hold[i]; 
    hold[i] = hold[j]; 
    hold[j] = temp; 
      hold[i]=j; 
    this.repaint();//can use eapint with a class that extends JPanel 
} 

    public void swap(int i, int j)//position of the two elements to swap in the array 
{ 
    try { 
     th.sleep(2000);//sleep before swapping because else user won't see original array since it would swap and then sleep 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    int temp = hold[i]; 
    hold[i] = hold[j]; 
    hold[j] = temp; 
      this.repaint();//can use eapint with a class that extends JPanel 
} 


public int get(int pos) 
{ 
    return hold[pos]; 

} 

}

這是我的GUI的一部分將導致編譯:

JavaCompiler jc = null; 
    StandardJavaFileManager sjfm = null; 
    File javaFile = null; 
    String[] options = null; 
    File outputDir = null; 
    URL[] urls = null; 
    URLClassLoader ucl = null; 
    Class clazz = null; 
    Method method = null; 
    Object object = null; 



     try 
     { 
     jc = ToolProvider.getSystemJavaCompiler(); 
     sjfm = jc.getStandardFileManager(null, null, null); 
     File[] files = new File[1]; 
     //files[0] = new File("C:/Users/user/Documents/NetBeansProjects/My_Final_Year_Project/myArray.java"); 
     //files[1] = new File("C:/Users/user/Documents/NetBeansProjects/My_Final_Year_Project/Tool.java"); 
     files[0] = new File("C:/Users/user/Documents/NetBeansProjects/My_Final_Year_Project/userDefined.java"); 
     // getJavaFileObjects’ param is a vararg 
     Iterable fileObjects = sjfm.getJavaFileObjects(files); 
     jc.getTask(null, sjfm, null, null, null, fileObjects).call(); 
     // Add more compilation tasks 
     sjfm.close(); 
     options = new String[]{"-d", "C:/Users/user/Documents/NetBeansProjects/My_Final_Year_Project"}; 
     jc.getTask(null, sjfm, null, Arrays.asList(options), null, fileObjects).call(); 

     outputDir = new File("C:/Users/user/Documents/NetBeansProjects/My_Final_Year_Project"); 
     urls = new URL[]{outputDir.toURL()}; 
     ucl = new URLClassLoader(urls); 
     clazz = ucl.loadClass("userDefined"); 


     method = clazz.getMethod("user", null); 
     object = clazz.newInstance(); 
     Object ob = method.invoke(object, null); 


     } 

這是一個用戶定義算法(userDefined.java)的例子:

import java.awt.*; 
import javax.swing.*; 


public class userDefined 
{ 
public void user() 
{ 
    int [] numArr = {1,3,1,-1,5,-5,0,7,12,-36}; 
    myArray myArray = new myArray(numArr); 

    JFrame frame = new JFrame("Rectangles"); 

    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
    frame.setSize(360, 300); 
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true); 
     frame.add(myArray); 

    for (int i=myArray.length(); i>1; i--) 
    { 
     for (int j=0; j<i-1; j++) 
     { 
      if (myArray.get(j) > myArray.get(j+1)) 
      { 
       myArray.swap(j, j+1); 
      } 
     } 
    } 

} 

}

我得到的問題是,如果我嘗試使用反射像上面;我只看到一個不顯示動畫的白色窗口),但只在最後顯示結果。

然而如果使用本代替反射(和在userDefined.java改變方法空隙用戶()來靜態無效的主要(字符串參數)):

 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
     if(compiler.run(null, null, null, "userDefined.java") != 0) { 
     System.err.println("Could not compile."); 
     System.exit(0); 
     } 
     try { 
     Runtime rt = Runtime.getRuntime(); 
     Process pr = rt.exec("java "+"userDefined"); 
     BufferedReader input = new BufferedReader(new    InputStreamReader(pr.getInputStream())); 
     String line=null; 
     while((line=input.readLine()) != null) { 
     System.out.println(line); 
     } 
     } catch(Exception e) { 
     System.out.println(e.toString()); 
     e.printStackTrace(); 

它炒菜鍋規定,第一編譯後我將myArray類放在與userDefined.java相同的文件夾中。在這種情況下,我可以看到動畫正確發生。

如何使用反射來調用main方法而不是使用類的實例。 請真的需要一些幫助。謝謝!

+0

你問如何反思地調用一個靜態方法而不是一個實例方法? – 2011-02-23 13:05:59

+0

是的,如果我將public void user()更改爲public static void main(String [] args),我應該如何反思性地調用main方法。此外,我不明白爲什麼我使用實例來調用方法'用戶'時得到白色框架。 – user630167 2011-02-23 13:14:27

+0

tl; dr。對不起 - 你能提煉出來嗎? – Marcin 2011-02-23 13:18:21

回答

4

您違反/錯過了第一個揮杆規則:只在EDT(Event Dispatch Thread)中存取揮杆組件。

當您使用main方法啓動程序時,您違反了該規則。這種情況正常,但可能會產生各種奇怪的效果。這不是一個理論上的警告,它發生在我身上,它不是很好。

當您使用代碼中的反射來運行它時,您最有可能在EDT中,因此您的算法在GUI再次更新之前運行(這也發生在EDT上)。這就是爲什麼你只能看到算法的最終結果。

做的正確的方式,這將是: 運行在一個單獨的線程算法,並確保你的myArray的組件都發生變化的EDT,使用SwingUtilities.invokeAndWait或SwingUtilities.invokeLater

+0

謝謝我只是做了你所說的,現在它的工作正常。 – user630167 2011-02-24 08:12:40

+0

在這種情況下,我很高興通過點擊左側投票計數器下的複選標記來接受答案。歡迎來到stackoverflow – 2011-02-24 11:15:32