-1

I know there's no direct replacement for java.awt.Canvas in swing, and I know I'm supposed to use a JPanel and override paintComponent, for example like so:

public void paintComponent(Graphics g) {
    g.setColor(Color.black);
    g.drawOval(0, 0, 100, 100);
}

And this would draw a black circle on the JPanel when it is created. The problem I have is that I want a dynamic canvas: I want to be able to draw things in response to user input, and redraw continuously, not just once when the application starts. An example would be having a moving object on a canvas, that would need to be redrawn at a rate of say 60 frames per second. How could I achieve this without using AWT components?

EDIT: what I mean is, in an actual canvas, I'd be able to arbitrarily call, say, drawOval anywhere in my code, and that would draw an oval on the canvas; is this doable with JPanel?

Bluefire
  • 13,519
  • 24
  • 74
  • 118
  • 1
    For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). – Andrew Thompson Dec 26 '17 at 13:23
  • @AndrewThompson that would apply if I were asking "I'm trying to do X but my code is doing Y and I don't know why", whereas my question is "how do I even begin to do X?" – Bluefire Dec 27 '17 at 13:01

2 Answers2

3

Store the information to be drawn (e.g. a Shape or a group of them) and call repaint() from a Swing Timer. Each time the paintComponent(..) method is called, first call the super(..) method to erase the previous drawings, then iterate the list of shapes, move them if necessary, and draw each one.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • Thanks! Is there a reason that swing doesn't have Canvas from AWT? It seems like a silly thing to omit... – Bluefire Dec 27 '17 at 13:02
2

Here's one way to do it:

public class Renderer extends JComponent implements ActionListener {
    private int x;        

    public Renderer() {
        Timer timer = new Timer(1000/60, this);
        timer.start();
        x = 0;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paint(g);
        // drawing code
        g.setColor(Color.black);
        g.drawOval(x, 0, 100, 100);
    }

    private void update() {
        this.x++;    
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        update();
        repaint();      
    }

}

Now just add this to your component (JPanel or whatever):

comp.add(new Renderer());
sam46
  • 1,273
  • 9
  • 12