java - 如果在 JPanel 上画得太远,我怎样才能再次画一个圆

标签 java swing jpanel paintcomponent

我正在尝试制作一个在 JPanel 顶部以 7 个圆圈开头的程序。所有圆圈都有随机的大小和颜色。这些圆圈从屏幕顶部开始向下移动,一旦到达 JPanel 底部,它们就会重新出现在 JPanel 顶部并再次向下移动。我已经可以让圆圈向下移动,但我不确定如何将它们再次拉回顶部。我创建了一个名为 ReplaceCircle 的方法,用于将圆圈绘制回 JPanel 顶部,但它不起作用。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import java.util.Random;
import javax.swing.JPanel;
import javax.swing.Timer;

public class keyExample extends JPanel implements ActionListener, KeyListener {

    private Circle[] circles = new Circle[7];

    Timer t = new Timer(5, this);
//current x and y
    double x = 150, y = 200;
    double changeX = 0, changeY = 0;
    private Circle c1, c2, c3, c4, c5, c6, c7, circleone;
    private int circlex = 10, circley = 0; // makes initial starting point of circles 0
    private int newCirclex = 0, newCircley = 0;
    private javax.swing.Timer timer2;
    private Random num = new Random();
    private int s = num.nextInt(8);

    public keyExample() {

        t.start();
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);
        Random num = new Random();
        Random colors = new Random();

        Color color1 = new Color(colors.nextInt(256), colors.nextInt(256), colors.nextInt(256));
        Color color2 = new Color(colors.nextInt(256), colors.nextInt(256), colors.nextInt(256));
        Color color3 = new Color(colors.nextInt(256), colors.nextInt(256), colors.nextInt(256));
        Color color4 = new Color(colors.nextInt(256), colors.nextInt(256), colors.nextInt(256));
        Color color5 = new Color(colors.nextInt(256), colors.nextInt(256), colors.nextInt(256));
        Color color6 = new Color(colors.nextInt(256), colors.nextInt(256), colors.nextInt(256));
        Color color7 = new Color(colors.nextInt(256), colors.nextInt(256), colors.nextInt(256));

        int radius1 = num.nextInt(40);
        int radius2 = num.nextInt(20);
        int radius3 = num.nextInt(25);
        int radius4 = num.nextInt(45);
        int radius5 = num.nextInt(15);
        int radius6 = num.nextInt(40);
        int radius7 = num.nextInt(50);

        if (radius1 < 5) {
            radius1 = 10;
        } else if (radius2 < 5) {
            radius2 = 10;
        } else if (radius3 < 5) {
            radius3 = 10;
        } else if (radius4 < 5) {
            radius4 = 10;
        } else if (radius5 < 5) {
            radius5 = 10;
        } else if (radius6 < 5) {
            radius6 = 10;
        } else if (radius7 < 5) {
            radius7 = 10;
        } else {
        }
        c1 = new Circle(circlex, circley, radius1, color1);
        c2 = new Circle(circlex + 70, circley, radius2, color2);
        c3 = new Circle(circlex + 150, circley, radius3, color3);
        c4 = new Circle(circlex + 220, circley, radius4, color4);
        c5 = new Circle(circlex + 270, circley, radius5, color5);
        c6 = new Circle(circlex + 340, circley, radius6, color6);
        c7 = new Circle(circley + 410, circley, radius7, color7);

        circles[0] = c1;
        circles[1] = c2;
        circles[2] = c3;
        circles[3] = c4;
        circles[4] = c5;
        circles[5] = c6;
        circles[6] = c7;

        timer2 = new javax.swing.Timer(33, new MoveListener());
        timer2.start();

    }

    public void NewCircle() {
        for (int i = 0; i < circles.length; i++) {
            Random num = new Random();
            Random colors = new Random();
            Color color = new Color(colors.nextInt(256), colors.nextInt(256), colors.nextInt(256));
            int radius = num.nextInt(40);
            if (radius < 5) {
                radius = radius + 10;
            } else {
            }
            circles[i] = new Circle(circlex, circley, radius, color);

        }

    }

    public void replaceCircle() {
        int height = getHeight();
        newCircley = newCircley + s;
        circley = newCircley;
        Random num = new Random();
        int radius = num.nextInt(34);
        Random colors = new Random();
        Color color = new Color(colors.nextInt(256), colors.nextInt(256), colors.nextInt(256));
        if (circley > height) {
            c1 = new Circle(10, 0, radius, color);
        } else {
        }

    }

    public void createCircle() {

    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setColor(Color.BLUE);
        g2.fill(new Rectangle2D.Double(x, y, 40, 40));
        for (int i = 0; i < circles.length; i++) {
            circles[i].fill(g);
        }

    }

    public void actionPerformed(ActionEvent e) {
        repaint();
        x += changeX;
        y += changeY;
        changeX = 0;
        changeY = 0;

    }

    public void up() {
        if (y != 0) {
            changeY = -3.5;
            changeX = 0;
        }
    }

    public void down() {
        if (y <= 350) {
            changeY = 3.5;
            changeX = 0;

        }
    }

    public void left() {
        if (x >= 0) {
            changeX = -3.5;
            changeY = 0;
        }
    }

    public void right() {
        if (x <= 550) {
            changeX = 3.5;
            changeY = 0;
        }
    }

    private class MoveListener implements ActionListener {

        public void actionPerformed(ActionEvent e) {

            Random speed = new Random();

            int s2 = speed.nextInt(12);
            int s3 = speed.nextInt(4);
            int s4 = speed.nextInt(20);
            int s5 = speed.nextInt(7);
            int s6 = speed.nextInt(5);
            int s7 = speed.nextInt(8);

            c1.move(0, s);
            c2.move(0, s2);
            c3.move(0, s3);
            c4.move(0, s4);
            c5.move(0, s5);
            c6.move(0, s6);
            c7.move(0, s7);

            repaint();

        }
    }

    public void keyPressed(KeyEvent e) {
        int code = e.getKeyCode();
        if (code == KeyEvent.VK_UP) {
            up();
        }
        if (code == KeyEvent.VK_DOWN) {
            down();
        }
        if (code == KeyEvent.VK_RIGHT) {
            right();
        }
        if (code == KeyEvent.VK_LEFT) {
            left();

        }
    }

    public void keyTyped(KeyEvent e) {
    }

    public void keyReleased(KeyEvent e) {
    }

    public static void main(String[] args) {
        new keyExample();
    }
}

圆类

import java.awt.*;

公开课圈子{

    private int centerX, centerY, radius, coord;
    private Color color;

    public Circle(int x, int y, int r, Color c) {
        centerX = x;
        centerY = y;
        radius = r;
        color = c;

    }

    public void draw(Graphics g) {
        Color oldColor = g.getColor();
        g.setColor(color);
        g.drawOval(centerX - radius, centerY - radius, radius * 2, radius * 2);
        g.setColor(oldColor);

    }

    public void fill(Graphics g) {
        Color oldColor = g.getColor();
        g.setColor(color);
        g.fillOval(centerX - radius, centerY - radius, radius * 2, radius * 2);
        g.setColor(oldColor);
    }

    public boolean containsPoint(int x, int y) {
        int xSquared = (x - centerX) * (x - centerX);
        int ySquared = (y - centerY) * (y - centerY);
        int RadiusSquared = radius * radius;
        return xSquared + ySquared - RadiusSquared <= 0;
    }

    public void move(int xAmount, int yAmount) {
        centerX = centerX + xAmount;
        centerY = centerY + yAmount;
    }

}

最佳答案

更好的解决方案是为Circle提供一些方法来确定它出界时应该做什么,但是,代码太复杂了,我用这个来代替......

首先向您的 Circle 类添加 getBounds 方法...

public Rectangle getBounds() {
    int x = centerX - radius;
    int y = centerY - radius;
    return new Rectangle(x, y, radius * 2, radius * 2);
}

这将提供有关圆圈有多大以及位置的信息......

接下来,在您的 MoveListener 中,添加一个 checkBounds 方法...

public void checkBounds(Circle circle) {
    int height = getHeight();
    Rectangle bounds = circle.getBounds();

    if (bounds.y + bounds.height > height) {
        circle.move(0, -(height) + bounds.height);
    }
}

这将用于确定给定的Circle是否已超出可视区域的边界...

接下来,在 MoveListeneractionPerformed 方法中,检查每个圆圈...

c1.move(0, s);
checkBounds(c1);

依此类推...

更新了快速示例

所以,这是我一直在努力实现的目标的快速示例......

Drop Circles

这使用ArrayList作为Circles的主要容器,但是不需要太多的改变它来使用数组(事实上,某些部分会变得更容易)....

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DropCircles {

    public static void main(String[] args) {
        new DropCircles();
    }

    public DropCircles() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        protected static final int MAX_CIRCLES = 7;
        private List<Circle> circles;
        private Random rnd = new Random();

        public TestPane() {
            circles = new ArrayList<>(MAX_CIRCLES);
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    while (circles.size() < MAX_CIRCLES) {
                        circles.add(createCircle());
                    }

                    List<Circle> purge = new ArrayList<>(MAX_CIRCLES);
                    for (Circle circle : circles) {
                        Point p = circle.getLocation();
                        p.y += circle.getYDelta();
                        if (p.y > getHeight()) {
                            purge.add(circle);
                        } else {
                            circle.setLocation(p);
                        }
                    }
                    circles.removeAll(purge);

                    repaint();
                }
            });
            timer.start();
        }

        protected Circle createCircle() {

            int x = rnd.nextInt(getWidth());
            int radius = 5 + rnd.nextInt(45);
            int speed = 1 + rnd.nextInt(8);

            if (x + radius > getWidth()) {
                x = getWidth() - radius;
            }

            Circle circle = new Circle(radius, new Color(rnd.nextInt(255), rnd.nextInt(255), rnd.nextInt(255)));
            circle.setLocation(x, 0);
            circle.setYDelta(speed);

            return circle;

        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            for (Circle circle : circles) {
                circle.paint(g);
            }
            g2d.dispose();
        }
    }

    public static class Circle {

        private final int radius;
        private final Color color;
        private int x;
        private int y;

        private int yDelta;

        public Circle(int radius, Color color) {
            this.radius = radius;
            this.color = color;
        }

        public void setLocation(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public void setLocation(Point p) {
            setLocation(p.x, p.y);
        }

        public Point getLocation() {
            return new Point(x, y);            
        }

        public void setYDelta(int yDelta) {
            this.yDelta = yDelta;
        }

        public int getYDelta() {
            return yDelta;
        }

        public void paint(Graphics g) {
            g.setColor(color);
            g.fillOval(x, y, radius, radius);
        }

    }

}

基本上发生的情况是,当Circle离开可视区域时,它会从“列表”中删除,并且在下一个刻度(Timer)上,创建新的Circle是为了确保屏幕上始终有七个圆圈(或大约有七个圆圈)。

如果你要使用数组。您可以简单地在当前Circle 的索引位置处的运动循环中创建一个新的Circle,从而有效地替换它...

关于java - 如果在 JPanel 上画得太远,我怎样才能再次画一个圆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20462128/

相关文章:

java - 如何用方向键移动矩形?

Java 卡布局,KeyListener 停止工作

Java连接四胜利检查

java - 如何从 Netbeans 中的 Java 应用程序项目中排除源文件?

java - Swing:在不触发回调的情况下以编程方式修改 UI

java - 如何访问在 java swing 中运行时实例化的对象的事件监听器

java - 我好像是在JPanel下画画的

java - Firebase 数据检索 java

Java小程序在本地运行找不到jar中的资源

Java8 ArchLinux arm 字体 NullPointerException