Проблема отражения Java - PullRequest
       31

Проблема отражения Java

0 голосов
/ 23 февраля 2011

Привет, я сейчас работаю над своим последним проектом;Мне нужно разработать инструмент визуализации алгоритма.Мне нужно обслуживать определенные пользователем алгоритмы;это анимация алгоритма, который пользователь вводит в текстовом редакторе, предоставленном в моем инструменте.

Я использую API компилятора Java для компиляции кода, набранного и сохраненного пользователем.Мой инструмент предлагает набор классов, которые пользователь может использовать в своем алгоритме.

Например:

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];

}

}

Это часть моего графического интерфейса, которая вызовет компиляцию:

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

}

}

Проблема, с которой я сталкиваюсь, заключается в том, что если я попытаюсь использовать отражение, как описано выше;Я получаю только белое окно, которое не показывает анимацию), а просто отображает результат в самом конце.

Однако, если я использую это вместо отражения (и меняю метод void user () на static void main(строковые аргументы) в 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 вместо использования экземпляра класса.Пожалуйста, мне действительно нужна помощь с этим.Спасибо!

1 Ответ

4 голосов
/ 23 февраля 2011

Вы нарушаете / неправильно используете первое правило свинга: доступ к компонентам свинга возможен только в EDT (Thread Dispatch Thread).

Когда вы запускаете свою программу, используя основной метод, вы нарушаете это правило.Это работает, но может иметь все виды странных эффектов.Это не теоретическое предупреждение, оно случилось со мной, и это нехорошо.

Когда вы запускаете его, используя отражение от вашего кода, вы, скорее всего, находитесь в EDT, поэтому ваш алгоритм работает полностью до того, как GUI получитобновляется снова (что также происходит на EDT).Вот почему вы видите только конечный результат алгоритма.

Правильный способ сделать это будет: Запустите алгоритм в отдельном потоке и убедитесь, что все изменения в вашем компоненте myArray происходят в EDT, используя SwingUtilities.invokeAndWait или SwingUtilities.invokeLater

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...