Java applet repaint a moving circle

谁说胖子不能爱 提交于 2020-01-13 07:07:33

问题


I've just moved over from Pygame so Java 2D in an applet is a little new to me, especially when it comes to repainting the screen. In pygame you can simply do display.fill([1,1,1]) but how do I do this in an applet in Java? I understand the use of repaint() but that doesn't clear the screen - any moving object is not 'removed' from the screen so you just get a long line of painted circles.

Here's my code that I've been testing with:

package circles;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Random;

public class circles extends Applet implements Runnable {
    private static final long serialVersionUID = -6945236773451552299L;
    static Random r = new Random();

    String msg = "Click to play!";
    static int w = 800, h = 800;

    int[] txtPos = { (w/2)-50,(h/2)-50 };
    int[] radiusRange = { 5,25 };
    int[] circles;
    static int[] posRange;

    int x = 0, y = 0;
    int radius = 0;
    int cursorRadius = 10;

    boolean game = false;

    public static int[] pos() {
        int side = r.nextInt(5-1)+1;
        switch(side) {
            case 1:
                posRange = new int[]{ 1,r.nextInt(w),r.nextInt((h+40)-h)+h,r.nextInt(270-90)+90 };
                break;
            case 2:
                posRange = new int[]{ 2,r.nextInt((w+40)-w)+w,r.nextInt(h),r.nextInt(270-90)+90 };
                break;
            case 3:
                posRange = new int[]{ 3,r.nextInt(w),r.nextInt(40)-40,r.nextInt(180) };
                break;
            case 4:
                posRange = new int[]{ 4,r.nextInt(40)-40,r.nextInt(h),r.nextInt(180) };
                break;
        }
        System.out.println(side);
        return posRange;
    }
    public void start() {
        setSize(500,500);
        setBackground(Color.BLACK);
        new Thread(this).start();
    }

    public void run() {

    }
    public void update(Graphics g) {
        paint(g);
    }

    public void paint(Graphics e) {
        Graphics2D g = (Graphics2D) e;

        if(System.currentTimeMillis()%113==0) {
            x+=1;
            y+=1;
        }

        g.setColor(Color.BLUE);
        g.fillOval(x,y,20,20);

        repaint();
    }
}

回答1:


  1. You need to call super.paint(g); in your paint method, as to not leave paint artifacts.

  2. Never call repaint() from inside the paint method

  3. Don't explicitly call paint, as you do in update(), when you mean to call reapaint()

  4. just update the x and y values from inside the update() method, then call repaint()

  5. You don't need to take a Graphics argument in update()

  6. You need to call update() somewhere repeatedly in a loop, as it updates the x and y and reapint()s

  7. If your class is going to be a Runnable, then you should put some code in the run() method. That's probably where you should have your loop


import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;

public class circles extends Applet implements Runnable {

    int x = 0, y = 0;

    public void start() {
        setSize(500, 500);
        setBackground(Color.BLACK);
        new Thread(this).start();
    }

    public void run() {
        while (true) {
            try {
                update();
                Thread.sleep(50);

            } catch (InterruptedException ex) {

            }
        }
    }

    public void update() {
        x += 5;
        y += 6;
        repaint();
    }

    public void paint(Graphics e) {
        super.paint(e);
        Graphics2D g = (Graphics2D) e;
        g.setColor(Color.BLUE);
        g.fillOval(x, y, 20, 20);

    }
}

Side Notes

  • Why use Applets in the first place. If you must, why use AWT Applet and not Swing JApplet? Time for an upgrade.

Here's how I'd redo the whole thing in Swing, using a Swing Timer instead of a loop and Thread.sleep, as you should be doing.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Circle extends JPanel{
    private static final int D_W = 500;
    private static final int D_H = 500;

    int x = 0;
    int y = 0;
    public Circle() {
        setBackground(Color.BLACK);

        Timer timer = new Timer(50, new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                x += 5;
                y += 5;
                repaint();
            }
        });
        timer.start();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.BLUE);
        g.fillOval(x, y, 20, 20);

    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(D_W, D_H);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new Circle());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

  • See How to use Swing Timers

  • See Create GUIs with Swing

  • Here's more advanced example for you to look at and ponder.

UPDATE

"Problem is, that's a JPANEL application. I specifically want to make an applet easily usable on a web page. "

You can still use it. Just use the JPanel. Take out the main method, and instead of Applet, use a JApplet and just add the JPanel to your applet. Easy as that.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.Timer;

public class CircleApplet extends JApplet {

    @Override
    public void init() {
        add(new Circle());
    }

    public class Circle extends JPanel {

        private static final int D_W = 500;
        private static final int D_H = 500;

        int x = 0;
        int y = 0;

        public Circle() {
            setBackground(Color.BLACK);

            Timer timer = new Timer(50, new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    x += 5;
                    y += 5;
                    repaint();
                }
            });
            timer.start();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.BLUE);
            g.fillOval(x, y, 20, 20);

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(D_W, D_H);
        }

    }
}


来源:https://stackoverflow.com/questions/22273376/java-applet-repaint-a-moving-circle

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