Applet AWT Canvas not updating graphics

166 Views Asked by At

I am trying to program a basic plotter using Applets. I need to use Applets specifically.

For the polt I have created a separate Canvas, but I have encountered a problem I cannot solve. When I draw any graph for the first time, it is drawn nicely. However, the canvas is not being repainted properly afterwards - I see in the debugging screen that the repaint() method was called and the paint() is invoked, but no graphics are updated.

Here is the code:

public class MyCanvas extends Canvas{
int w,h;   //width and height
int samples;
ArrayList<Double> eqValues = new ArrayList<>();
MyCanvas(int wi, int he) //constructor
{ w=wi; h=he;
    setSize(w,h); //determine size of canvas
    samples=wi-20;
}
public void paint(Graphics g)
{
    int y0=0, y1; //previous and new function value
    g.setColor(Color.yellow);
    g.fillRect(0,0,w,h);   //clear canvas
    g.setColor(Color.black);
    if (eqValues.size()>0) { // draw new graph
        for (int t = 1; t <= samples; t = t + 1) {
            y1 = eqValues.get(t).intValue();
            g.drawLine(10 + t - 1, h  - y0, 10 + t, h  - y1);
            y0 = y1;
        }
    }
    System.out.println("Repainted");
    /*g.drawLine(10,10,10,h-10);   //y-axis
    g.drawLine(10,h/2,w-10,h/2); //x-axis
    g.drawString("P",w-12,h/2+15);
    g.drawString("P/2",w/2-13,h/2+15);
    g.drawLine(w-10,h/2-2,w-10,h/2+2); //horizontal marks
    g.drawLine(w/2, h/2-2,w/2, h/2+2);*/
}

public void drawSine(double amp, double xCoef, double phase){
    for (int j=0;j<=samples;j++){
        eqValues.add(amp*Math.sin(xCoef*Math.PI*j/samples + Math.PI*phase/180)+0.5+h/2);
    }
    repaint();
    System.out.println("Got sine vals");
}

public void drawFOeq(double sc, double fc){
    for (int j=0;j<=samples;j++){
        eqValues.add(sc*j+fc);
    }
    repaint();
    System.out.println("Got FO eq vals");
}
}

Thanks in advance!

1

There are 1 best solutions below

1
On BEST ANSWER

The problem is when you add values to the ArrayList: you are putting them after the ones already in the ArrayList (with the add(Double) method). If you just want to clear the plot and draw a new function use the clear() method in the ArrayList of values before adding the new ones:

public void drawSine(double amp, double xCoef, double phase) {
    eqValues.clear();    //this clear the ArrayList
    ......
    repaint();
    ......
}

public void drawFOeq(double sc, double fc){
    eqValues.clear();    //this clear the ArrayList
    ......
    repaint();
    ......
}

If you want to plot multiple functions you have to create different ArrayList or, even better, store in the ArrayList all points (for example with java.awt.Point):

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;

public class MyCanvas extends Canvas {

    int w, h; // width and height
    int samples;
    ArrayList<Point> eqValues = new ArrayList<>();              //Point constructor receives 2 int arguments: x and y; however, his methods getX() and getY() return double values

    // constructor
    MyCanvas(int wi, int he) {
        w = wi;
        h = he;
        setSize(w, h);                                          // determine size of canvas
        samples = wi - 20;
    }

    public void paint(Graphics g) {
        int x1, y0, y1;                                         // previous and new function value

        g.setColor(Color.yellow);
        g.fillRect(0, 0, w, h);                                 // clear canvas

        g.setColor(Color.black);
        if (eqValues.size() > 0) {                              // draw new graph
            y0 = (int) Math.round(eqValues.get(0).getY());      // first line must start at the first point, not at 0,h
            for (Point p : eqValues) {                          // iterates over the ArrayList
                x1 = (int) Math.round(p.getX());
                y1 = (int) Math.round(p.getY());
                g.drawLine(10 + x1 - 1, h - y0, 10 + x1, h - y1);
                y0 = y1;
            }
        }

        System.out.println("Repainted");

    }

    public void drawSine(double amp, double xCoef, double phase) {
        for (int j = 0; j <= samples; j++) {
            eqValues.add(new Point(j, (int) Math
                    .round(amp * Math.sin(xCoef * Math.PI * j / samples + Math.PI * phase / 180) + 0.5 + h / 2)));
        }
        repaint();
        System.out.println("Got sine vals");
    }

    public void drawFOeq(double sc, double fc) {
        for (int j = 0; j <= samples; j++) {
            eqValues.add(new Point(j, (int) Math.round(sc * j + fc)));
        }
        repaint();
        System.out.println("Got FO eq vals");
    }
}