简体   繁体   English

Java Applet重绘运动圈

[英]Java applet repaint a moving circle

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. 我刚刚从Pygame搬走了,所以小程序中的Java 2D对我来说有点新,尤其是在重新绘制屏幕时。 In pygame you can simply do display.fill([1,1,1]) but how do I do this in an applet in Java? 在pygame中,您可以简单地执行display.fill([1,1,1])但是如何在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. 我了解repaint()的用法,但不能清除屏幕-不会从屏幕上“移除”任何移动的对象,因此您只能获得一长行绘制的圆圈。

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. You need to call super.paint(g); 您需要调用super.paint(g); in your paint method, as to not leave paint artifacts. 在您的paint方法中,以免留下绘画痕迹。

  2. Never call repaint() from inside the paint method 切勿从paint方法内部调用repaint()

  3. Don't explicitly call paint , as you do in update() , when you mean to call reapaint() 当您打算调用reapaint()时,请不要像在update()那样显式调用paint

  4. just update the x and y values from inside the update() method, then call repaint() 只需从update()方法内部更新xy值,然后调用repaint()

  5. You don't need to take a Graphics argument in update() 您不需要在update()使用Graphics参数

  6. You need to call update() somewhere repeatedly in a loop, as it updates the x and y and reapint() s 您需要在循环中的某处重复调用update() ,因为它会更新xy以及reapint()

  7. If your class is going to be a Runnable , then you should put some code in the run() method. 如果您的类将是Runnable ,则应在run()方法中放入一些代码。 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. 为什么要首先使用Applet。 If you must, why use AWT Applet and not Swing JApplet ? 如果必须,为什么要使用AWT Applet而不是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. 这就是我应该使用Swing Timer而不是循环和Thread.sleep 重做 Swing中整个过程的方法。

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


UPDATE 更新

"Problem is, that's a JPANEL application. I specifically want to make an applet easily usable on a web page. " “问题是,这是一个JPANEL应用程序。我特别想使applet易于在网页上使用。”

You can still use it. 您仍然可以使用它。 Just use the JPanel. 只需使用JPanel。 Take out the main method, and instead of Applet, use a JApplet and just add the JPanel to your applet. 取出主要方法,使用JApplet代替Applet,然后将JPanel添加到您的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);
        }

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM