【问题标题】:Java applet repaint a moving circleJava小程序重绘一个移动的圆圈
【发布时间】:2014-04-11 23:23:45
【问题描述】:

我刚从 Pygame 搬过来,所以 Applet 中的 Java 2D 对我来说有点新鲜,尤其是在重新绘制屏幕时。在 pygame 中,您可以简单地执行display.fill([1,1,1]),但如何在 Java 的小程序中执行此操作?我了解repaint() 的使用,但这并不能清除屏幕 - 任何移动的物体都不会从屏幕上“移除”,所以你只会得到一长串画圈。

这是我一直在测试的代码:

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

【问题讨论】:

    标签: java applet awt graphics2d


    【解决方案1】:
    1. 您需要在您的paint 方法中调用super.paint(g);,以免留下绘画伪影。

    2. 永远不要从paint方法内部调用repaint()

    3. 当你打算调用reapaint()时,不要像在update()中那样显式调用paint

    4. 只需从update() 方法内部更新xy 值,然后调用repaint()

    5. 您不需要在update() 中使用Graphics 参数

    6. 您需要在循环中反复调用update(),因为它会更新xyreapint()s

    7. 如果你的类是Runnable,那么你应该在run()方法中加入一些代码。这可能就是你应该有循环的地方


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

    旁注

    • 首先为什么要使用小程序。如果必须,为什么要使用 AWT Applet 而不是 Swing JApplet?是时候升级了。

    这是我在 Swing 中重做整个事情的方法,使用 Swing Timer 而不是循环和 Thread.sleep,正如你应该做的那样。

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


    更新

    “问题是,这是一个 JPANEL 应用程序。我特别想让一个小程序在网页上易于使用。”

    您仍然可以使用它。只需使用 JPanel。取出 main 方法,而不是 Applet,使用 JApplet 并将 JPanel 添加到您的 applet。就这么简单。

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

    【讨论】:

    • +1 Applet vs JApplet 以及所有 1-7 项 :)
    • 我几乎已经修复了所有问题,感谢您回答如此愚蠢的问题!现在我的圆圈在移动时不断闪烁/闪烁,我将如何解决这个问题?谢谢!
    • 问题是,这是一个 JPANEL 应用程序。我特别想让一个小程序在网页上易于使用。
    • @HaydenPerry 你仍然可以使用它。只需使用JPanel。取出main 方法,而不是Applet,使用JApplet 并将JPanel 添加到您的小程序中。就这么简单。
    • @HaydenPerry 查看我的最后一次更新
    猜你喜欢
    • 2019-10-17
    • 2012-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多