Flickering white on canvas

这一生的挚爱 提交于 2019-12-14 03:23:37

问题


I figured out a solution minutes after posting, but due to low reputation I couldn't delete the post

For the fun of it I decided to start working on something which might turn into a game at some point.

I'm trying to draw some circles and move them in a given direction currently. This causes flickering. It's very likely that I oversee something very basic but I can't figure out why it doesn't render smoothly.

My board class looks something like (removed what I deemed unnecessary):

public class Board extends Canvas implements Runnable {

    public static void main(String[] args) {
        Board board = new Board();

        board.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));

        JFrame frame = new JFrame("Circles");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(board);
        frame.pack();

        frame.setVisible(true);

        board.start();
    }

    @Override
    public void run() {
        while (running) {
            process();
            repaint();

            try {
                Thread.sleep(15);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

The paint method:

    public void paint(Graphics g1) {
        super.paint(g1);
        Graphics2D g = (Graphics2D) g1;
        for (Ball ball : Ball.BALLS) {
            g.drawOval((int) ball.getLocation().getX(), (int) ball.getLocation().getY(), ball.getRadius(),  ball.getRadius());
        }
    }

My process method:

private void process() {
    if (utilities.randInt(1, 100) < 10 && Ball.getBallCount() < 40) {
        Ball.spawnNew(this);
    }
    for (Ball ball : Ball.BALLS) {
        ball.move(this);
    }
    Ball.BALLS.removeAll(Ball.TO_REMOVE);
    Ball.TO_REMOVE.clear();
}

The move method basically increments the x-value of the ball by a given value each time its called (moving it right).

Like I said, I'm unsure why it flickers so if you have any pointers please do tell.

Thanks!


回答1:


This sounds like a case where you need to perform double-buffering, so that one copy of your canvas can remain shown while you are updating the other.

You're using AWT here, and I don't know how to implement double-buffering manually with AWT. However, if you're willing to use Swing here you can take advantage of automatic double-buffering. See the question about How to make canvas with Swing? as well as Oracle Technology Network's article on Painting in AWT and Swing.

The basic idea would be:

  1. extend javax.swing.JPanel instead of Canvas (which means when you override paint(Graphics) you're now overriding it from javax.swing.JComponent instead of java.awt.Component)
  2. create a constructor with super(true) to enable double-buffering.

Edit: Also, as iccthedral points out, you're better off overriding paintComponent(Graphics) and including a call to super.paintComponent(Graphics). See Difference between paint, paintComponent and paintComponents in Swing.




回答2:


You need double buffering. To do this you need to create a BufferedImage and get the Graphics from it. Paint everything to the image, render the image on to the screen, then finally fill the image with a the background color or image to reset it.

Sample:

//one time instantiation
BufferedImage b = new BufferedImage(width, height, mode);

In paint(Graphics g):

Graphics buffer = b.getGraphics();
//render all of the stuff on to buffer
Graphics2D g = (Graphics2D) buffer;
    for (Ball ball : Ball.BALLS) {
        g.drawOval((int) ball.getLocation().getX(), (int) ball.getLocation().getY(), ball.getRadius(),  ball.getRadius());
    }
g1.drawImage(b, 0, 0, width, height, null);
g.setColor(Color.BLACK);
//reset the image
g.drawRect(0, 0, width, height);
g.dispose();


来源:https://stackoverflow.com/questions/24559888/flickering-white-on-canvas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!