0

嗨,我目前正在做最后一年的项目;我需要开发一个算法可视化工具。我需要满足用户定义的算法;这是动画用户在我的工具中提供的文本编辑器中键入的算法。

我正在使用 Java Compiler 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 中将方法 void user() 更改为 static void main(string args)):

        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 方法而不是使用类的实例。请我真的需要一些帮助。谢谢!

4

1 回答 1

4

您违反/误用了摇摆的第一条规则:仅在 EDT(事件调度线程)中访问摇摆组件。

当您使用 main 方法启动程序时,您违反了该规则。这恰好有效,但可能会产生各种奇怪的效果。这不是理论上的警告,它发生在我身上,并不好。

当您使用代码中的反射运行它时,您很可能在 EDT 中,因此您的算法在 GUI 再次更新之前完全运行(这也发生在 EDT 上)。这就是为什么你只看到算法的最终结果。

正确的方法是:在单独的线程中运行算法,并确保对 myArray 组件的所有更改都发生在 EDT 中,使用 SwingUtilities.invokeAndWait 或 SwingUtilities.invokeLater

于 2011-02-23T13:15:34.020 回答