Search code examples
javacanvasappletawtrepaint

Applet AWT Canvas not updating graphics


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!


Solution

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