简体   繁体   中英

Creating my own paint method in java

I want to create a method that creates 5 balls on a panel. Can somebody please help me get around this using the paint component method or creating my own draw method. As you can see bellow, i have a paint component method with a for loop that will loop 5 and create a ball in a random location, but unfortunately only one ball is being created.

import java.awt.*;
import java.util.Random;
import javax.swing.*;

public class AllBalls extends JPanel {
    int Number_Ball=5;
    int x,y;
    Graphics g;
    AllBalls(){
        Random r = new Random();
        x=r.nextInt(320);
        y=r.nextInt(550);
    }
public static JFrame frame;
    public static void main(String[] args) {
        AllBalls a= new AllBalls();
        frame= new JFrame("Bouncing Balls");
        frame.setSize(400,600);
        frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.add(a);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for(int i=0;i<Number_Ball;i++){
            g.fillOval(x, y, 30, 30);
        }
        repaint();
    }

}

In my paintComponent method, i created a for loop in which i wanted 5 ball to be created, but only one is being created on the screen.

Recommendations as per my comments:

  1. Get rid of the Graphics g variable as that will only hurt you.
  2. Consider creating a non-GUI Ball class, one that does not extend any Swing component and has its own paint(Graphics) method.
  3. If you need 5 balls, create an array of Ball objects in your AllBalls class.
  4. In paintComponent, iterate through the Balls painting each one by calling its paint or draw method (whatever you name the method).
  5. If you need to move the balls, do so in a Swing Timer that moves the balls and then calls repaint(). Whatever you do, do not call repaint() within the paintComponent method as this results in a bastardization of the method, and results in a completely uncontrolled animation. This method should be for painting and painting only and not for animation or code logic. Use the Swing Timer instead.
  6. Also don't randomize your ball locations within paintComponent, another recommendation made in a now-deleted answer. Again, paintComponent should be for painting and painting only and not for program logic or to change the state of your class. The randomization should be within your Swing Timer or game loop.

For example:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
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.*;

@SuppressWarnings({"serial", "unused"})
public class BallImages extends JPanel {
   private static final int PREF_W = 800;
   private static final int PREF_H = PREF_W;
   private static final int BALL_COUNT = 15;
   private static final Color[] COLORS = { Color.RED, Color.BLACK, Color.BLUE,
         Color.CYAN, Color.GREEN, Color.ORANGE, Color.PINK, Color.WHITE,
         Color.MAGENTA, Color.YELLOW };
   private static final int MIN_SPEED = 2;
   private static final int MAX_SPEED = 10;
   private static final int MIN_WIDTH = 10;
   private static final int MAX_WIDTH = 30;
   private static final int TIMER_DELAY = 15;
   private List<Ball> balls = new ArrayList<>();
   private Random random = new Random();

   public BallImages() {
      for (int i = 0; i < BALL_COUNT; i++) {
         int ballWidth = MIN_WIDTH + random.nextInt(MAX_WIDTH - MIN_WIDTH);
         Color ballColor = COLORS[random.nextInt(COLORS.length)];
         int ballX = ballWidth / 2 + random.nextInt(PREF_W - ballWidth / 2);
         int ballY = ballWidth / 2 + random.nextInt(PREF_H - ballWidth / 2);
         double direction = 2 * Math.PI * Math.random();
         double speed = MIN_SPEED + random.nextInt(MAX_SPEED - MIN_SPEED);
         Ball ball = new Ball(ballWidth, ballColor, ballX, ballY, direction,
               speed);
         balls.add(ball);
      }

      new Timer(TIMER_DELAY, new TimerListener()).start();
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      for (Ball ball : balls) {
         ball.draw(g2);
      }
   }

   @Override
   // set the component's size in a safe way
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         if (!BallImages.this.isDisplayable()) {
            ((Timer) e.getSource()).stop();
         }
         for (Ball ball : balls) {
            ball.move(PREF_W, PREF_H);
         }
         repaint();
      }
   }

   private class Ball {
      private int width;
      private Color color;
      private double x;
      private double y;
      private double direction;
      private double speed;
      private double deltaX;
      private double deltaY;

      public Ball(int width, Color color, int x, int y, double direction,
            double speed) {
         this.width = width;
         this.color = color;
         this.x = x;
         this.y = y;
         this.direction = direction;
         this.speed = speed;

         deltaX = speed * Math.cos(direction);
         deltaY = speed * Math.sin(direction);
      }

      public int getWidth() {
         return width;
      }

      public Color getColor() {
         return color;
      }

      public double getX() {
         return x;
      }

      public double getY() {
         return y;
      }

      public double getDirection() {
         return direction;
      }

      public double getSpeed() {
         return speed;
      }

      public void draw(Graphics2D g2) {
         g2.setColor(color);
         int x2 = (int) (x - width / 2);
         int y2 = (int) (y - width / 2);
         g2.fillOval(x2, y2, width, width);
      }

      public void move(int containerWidth, int containerHeight) {
         double newX = x + deltaX;
         double newY = y + deltaY;

         if (newX - width / 2 < 0) {
            deltaX = Math.abs(deltaX);
            newX = x + deltaX;
         }
         if (newY - width / 2 < 0) {
            deltaY = Math.abs(deltaY);
            newY = y + deltaY;
         }

         if (newX + width / 2 > containerWidth) {
            deltaX = -Math.abs(deltaX);
            newX = x + deltaX;
         }
         if (newY + width / 2 > containerHeight) {
            deltaY = -Math.abs(deltaY);
            newY = y + deltaY;
         }

         x = newX;
         y = newY;

      }
   }

   private static void createAndShowGui() {
      BallImages mainPanel = new BallImages();

      JFrame frame = new JFrame("BallImages");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.setResizable(false);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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