Java Simple Grapher Applet

时间:2015-01-05 11:45:17

标签: java applet

我试图在Java中创建一个简单的函数抽屉。 我使用ScriptEngine API从字符串中解析方程式,但绘制时速度非常慢。 还有另一种方法可以做同样的事情吗? 这是代码:

private String v;
@Override
public void init(){
    setSize(600,600);
    v = JOptionPane.showInputDialog("Input function:");
}
@Override
public void paint(Graphics g){
    drawQuadrants(g);
    drawEquation(g);
}
private void drawEquation(Graphics g) {
    g.setColor(Color.BLUE);
    ScriptEngineManager mgr = new ScriptEngineManager();
    ScriptEngine engine = mgr.getEngineByName("JavaScript");
    v = v.replace("sin", "Math.sin")
    .replace("cos", "Math.cos")
    .replace("sen", "Math.sin")
    .replace("tan", "Math.tan")
    .replace("tg", "Math.tan")
    .replace("log", "Math.log")
    .replace("Log(x)","(Math.log(x)/Math.LN10)");
    for(double x0 = -10;x0<=10;x0+=0.001){
        engine.put("x", x0);
        try {
            double y0 = (Double)engine.eval(v);
            drawPoint(g,x0,-y0);
        } catch (HeadlessException | ScriptException e) {
            e.printStackTrace();
        }
    }
}
private void drawQuadrants(Graphics g) {
    g.setColor(Color.BLACK);
    g.drawLine(0, 300, 600, 300);
    g.drawLine(300, 0, 300, 600);
    g.setFont(new Font("Arial",Font.BOLD,15));
    g.drawString("x", 580, 320);
    g.drawString("y", 280, 20);
    for(int l = 0;l<=600;l+=30){
        g.drawLine(l, 297, l, 303);
    }
    for(int l = 0;l<=600;l+=30){
        g.drawLine(297, l, 303, l);
    }
}
private void drawPoint(Graphics g, double x0, double y0) {
    int newx0 = (int)map((float)x0, (float)-10, (float)10, (float)0.0, (float)600.0);
    int newy0 = (int)map((float)y0, (float)-10, (float)10, (float)0.0, (float)600.0);
    g.drawOval(newx0, newy0, 1, 1);
}
public static final float map(float value, float start1, float stop1, float start2, float stop2)
{
    return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
}

3 个答案:

答案 0 :(得分:1)

嗯,你总是可以尝试我的代码,它简单快速而优雅。它还可以使用外部解析器绘制任何图形。

    import javax.swing.*;
    import java.awt.*;
     import java.util.Scanner;
       import net.objecthunter.exp4j.*;

     class math extends JFrame
     {
       public static void main(String args[])
      {
    math m=new math();
    m.setVisible(true);
    m.setLocationRelativeTo(null);


}

public void paintallies(Graphics G1,double sf)
{int i;
 Graphics2D g21=(Graphics2D) G1;
 g21.setColor(Color.GREEN);
    for(i=0;i<=600;i=(int) (i+sf))
    {
        g21.drawLine(i,0,i,600);
        g21.drawLine(0,i,600,i);

    }

}
public void paintaxes(Graphics G1)
{
    Graphics2D g21=(Graphics2D) G1;
    g21.setColor(Color.BLACK);
    g21.drawLine(300,0,300,600);//y axis

    g21.drawLine(0,300,600,300); //x axis

}


public void paint(Graphics G)
{
    int i;
    double j,k;

    Scanner s=new Scanner(System.in);
    System.out.println("Enter input");
    String input=s.nextLine();
    System.out.println("Enter scale factor");
    double sf=s.nextDouble();
    double sff=300/sf;
    double kf=sff;
    double count=0;






    Graphics g2=(Graphics) G;
    paintallies(G,sf);
    paintaxes(G);

    g2.translate(300,300);
    do
    {
        kf=kf-(1/sf);
        count++;

    }while(kf>=0);
    double counts=2*count;


    Color c=Color.RED;
    g2.setColor(c.darker());

    double yarr[]=new double[(int)counts];
    double xarr[]=new double[(int)counts];



    Expression E=new ExpressionBuilder(input).variables("x").build();


     j=-sff; k=-sff;
    for(i=0;i<counts;i++)
    {

        xarr[i]=j;
        j=j+(1/sf);


        E.setVariable("x",k);
        yarr[i]=E.evaluate();
        k=k+(1/sf);

        xarr[i]=sf*xarr[i];
        yarr[i]=-sf*yarr[i];

    }

    for(i=0;i<counts;i++)
    {
        if(i==counts-1)
        {
            break;
        }
        else
        {
        g2.drawLine((int)xarr[i],(int)yarr[i],(int)xarr[i+1],(int)yarr[i+1]);

        }
    }


}






math()
{
    super("Grapher");
    setSize(600,600);
    setResizable(true);



}

}

答案 1 :(得分:0)

一个悬而未决的成果可能是增加drawEquation()方法中for循环步骤的值。选择此值时,请考虑水平最大约2K至3K像素。然而,你在X轴上迭代超过20K点。首先尝试x0 + = 0.01,然后根据需要进行调整。这可能会导致程序在1/10的时间内运行。

答案 2 :(得分:0)

如果你这样会快得多 - 将 ScriptEngineManager mgr 对象作为成员变量并创建一次(在类的构造函数中)

  • 仅在输入对话框中的文本发生更改时才调用 drawEquation 中的解析和计算,而不是在每次绘制中。您可以将计算值保存在两个数组中(一个数组用于x,另一个用于y值)。

作为一般规则(对于我所知道的每个图形工具),onDraw方法应该小而快。

  • 不在onDraw中执行对象操作和初始化。那个垃圾收集器有很多工作要做。
  • 如果可以在之前执行这些计算,则不要在onDraw中执行大量计算。

编辑: 计算并绘制您需要绘制的点。您需要知道Graphic对象的宽度,计算 for 循环的增量值,并且只有 g.width()迭代次数。更多迭代只是浪费 - 您在同一个屏幕位置绘制了许多点。