繁体   English   中英

在Java中创建我自己的绘画方法

[英]Creating my own paint method in java

我想创建一个在面板上创建5个球的方法。 有人可以帮助我使用paint组件方法或创建自己的draw方法来解决此问题。 正如您在下面看到的那样,我有一个带有for循环的paint component方法,该方法将循环5并在一个随机位置创建一个球,但是不幸的是,仅创建了一个球。

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

}

在我的paintComponent方法中,我创建了一个for循环,其中希望创建5个球,但是在屏幕上只创建了一个。

根据我的意见的建议:

  1. 摆脱Graphics g变量,因为这只会伤害您。
  2. 考虑创建一个非GUI Ball类,该类不扩展任何Swing组件并具有自己的paint(Graphics)方法。
  3. 如果需要5个球,请在AllBalls类中创建一个Ball对象数组。
  4. 在paintComponent中,通过调用其paint或draw方法(无论您使用哪种方法)来遍历Balls绘画每个对象。
  5. 如果需要移动球,请在Swing计时器中移动球,然后调用repaint()。 无论做什么,都不要在paintComponent方法内调用repaint() ,因为这会导致方法的混用,并导致完全不受控制的动画。 此方法应仅用于绘画,而不能用于动画或代码逻辑。 请改用Swing计时器。
  6. 另外,不要在paintComponent中随机放置球的位置,这是现已删除的答案中提出的另一项建议。 同样,paintComponent应该仅用于绘画,而不能用于程序逻辑或更改类的状态。 随机化应该在您的Swing Timer或游戏循环中。

例如:

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

暂无
暂无

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

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