如果JPanel上的圆弧过大,我该如何再次绘制圆弧 [英] how can i draw a circle again if it goes too far on a JPanel

查看:113
本文介绍了如果JPanel上的圆弧过大,我该如何再次绘制圆弧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个以JPanel顶部的7个圆圈开头的程序.所有的圆圈都有随机的大小和颜色.圆圈从屏幕的顶部开始,一旦到达JPanel的底部,则向下移动,它们应重新出现在JPanel的顶部,然后再次向下移动.我已经可以使圆圈向下移动,但是不确定如何再次将其拉回顶部.我制作了一个名为replaceCircle的方法,用于将圆画回到JPanel的顶部,但是它不起作用.

I am trying to make a program that starts with 7 circles at the top of a JPanel. All the circles have a random size and color. The circles start at the top of the screen and move downwards once they reach the bottom of the JPanel they should reappear at the top of the JPanel and move downwards again. I can already make the circles move downwards but I am unsure of how to draw them back at the top again. I made a method called replaceCircle to use to draw the circles back at the top of the JPanel but its not working.

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提供一些确定超出范围时应该执行的操作的方法,但是,代码是如此复杂我改用这个...

The better solution would be providing the Circle with some means to determine what it should do when it moves out of bounds, however, the code is so convoluted I used this instead...

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

Start by adding a getBounds method to your Circle class...

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

这将提供有关圆圈的大小和位置的信息...

This will provide information about how big and where the circle is...

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

Next, in your MoveListener, add a checkBounds method...

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是否已超出可见区域的范围...

This will be used to determine if a given Circle has moved beyond the bounds of the viewable area...

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

Next, in your MoveListener's actionPerformed method, check each circle...

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

等等...

使用快速示例进行更新

所以,这是我试图达到的目标的快速示例.

So, this is quick and fast example of what I've being trying to get to...

这使用ArrayList作为Circles的主要容器,但是使用数组将其更改不需要花费很多(实际上,某些部分会变得更容易)....

This uses an ArrayList as the primary container for the Circles, but it wouldn't take much to change it to use an array (in fact, some parts would become easier)....

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以确保存在屏幕上总是有七个圆圈(或左右).

Basically what happens is, as a Circle leaves the viewable area, it is removed from the "list" and on the next tick (of the Timer), a new Circle is created to ensure that there is always seven circles on the screen (or there abouts).

如果要使用数组.您只需在移动循环中在当前Circle的索引位置处创建一个新的Circle,有效地替换它...

If you were to use an array. You could simply create a new Circle in the movement loop at the index position of the current Circle, effectivly replacing it...

这篇关于如果JPanel上的圆弧过大,我该如何再次绘制圆弧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆