从 ArrayList 重新绘制类的实例 [英] Repainting an instance of a class from an ArrayList

查看:31
本文介绍了从 ArrayList 重新绘制类的实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,所以我对 Java Swing 很陌生,而且一般来说是 Java 的初学者.我目前的问题是我设计了一个城市景观".我正在研究一个飞来飞去的不明飞行物,但我随机生成的建筑物会继续再生.我想知道是否有一种方法可以将我的建筑物实例保存到我尝试过的 ArrayList 中,并在每次调用 Paint 时从该列表中绘制该选择. 我尝试了我的想法,然后我相信它只是在运行时崩溃了,因为它甚至没有打开 JFrame 而是在出错时产生错误.这是我所拥有的:

Ok so I am very new to Java Swing and a beginner in Java in general. My current problem is I have designed a "cityscape". I am working on a UFO flying around, but my randomly generated buildings continue to get regenerated. I am wondering if there is a way to save my instance of buildings to an ArrayList as I have attempted, and paint that selection from that list each time paint is called. I tried what I thought of and I believe it just crashed it when run, because it didn't even open a JFrame and instead produced errors upon errors. Here is what I have:

CityScape 类(主类):

CityScape class (the main class):

import java.awt.*; 
import javax.swing.*;
public class CityScape extends JPanel 
{     
  Buildings a = new Buildings ();
UFO b = new UFO();

  @Override
  public void paint (Graphics g)
  {
    //RememberBuildings.buildingList.get(1).paint(g);
    a.paint(g);
    b.paint(g);
  }
  public void move()
  {
    b.move();
  }


  public static void main(String[] args) throws InterruptedException
  { 
    JFrame frame = new JFrame("Frame"); 
    CityScape jpe = new CityScape();
    frame.add(jpe);
    frame.setSize(800, 750); 
    frame.setBackground(Color.BLACK);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    System.out.println(frame.getContentPane().getSize());
    while (true)
    {
      jpe.move(); //Updates the coordinates
      jpe.repaint(); //Calls the paint method
      Thread.sleep(10); //Pauses for a moment
    }
  }
}

Buildings 类(生成建筑物的类):

Buildings class (the class that generates the buildings):

import java.awt.*;

public class Buildings
{

  private int maxX = 784;
  private int maxY = 712;
  private int width = (int)(Math.random()*100+100);
  private int height = (int)(Math.random()*350+100);
  private  int rows = Math.round((height)/25);
  private int columns = Math.round(width/25);

  public void addBuilding()
  {
  RememberBuildings.addBuilding();
  }

  public void paint(Graphics g) 
  { 
    Graphics2D g2d = (Graphics2D) g;

    Color transYellow = new Color (255, 255, 0, 59);

    g2d.setColor(Color.BLACK);
    g2d.fillRect(0, 0, maxX, maxY);

    g2d.setColor(Color.WHITE);
    g2d.fillRect(5, 5, 25, 25);

    int a = 0;

    for (int i =10; i<634; i+=(a+10))//buildings
    {

      g2d.setColor(Color.GRAY);
      g2d.drawRect(i, maxY-height, width, height);
      g2d.fillRect(i, maxY-height, width, height);


      rows = Math.round((height)/25);
      columns = Math.round(width/25);

      for (int j = 1; j<=columns; j++)//windows
      {
        for (int k = 1; k<=rows; k++)
        {
          g2d.setColor(Color.BLACK);
          g2d.drawRect(i+5*j+20*(j-1), (maxY-height)+5*k+20*(k-1), 20, 20);
          if (Math.random()<0.7)
          {
            g2d.setColor(Color.YELLOW);
            g2d.fillRect(i+5*j+20*(j-1), (maxY-height)+5*k+20*(k-1), 20, 20);
          }
          else
          {
            g2d.setColor(Color.BLACK);
            g2d.fillRect(i+5*j+20*(j-1), (maxY-height)+5*k+20*(k-1), 20, 20);
            g2d.setColor(transYellow);
            g2d.fillRect(i+5*j+20*(j-1), (maxY-height)+5*k+20*(k-1), 20, 20);
          }
        }
      }
      addBuilding();
      a = width;
      height = (int)(Math.random()*462+100);
      width = (int)(Math.random()*100+100);

    }
  }
}

RememberBuildings 类(重点是向 ArrayList 添加实例):

RememberBuildings class (the point of this is to add an instance to an ArrayList):

import java.util.*;
public class RememberBuildings
{
  public static ArrayList<Buildings> buildingList = new ArrayList<Buildings>();

  public static void addBuilding()
  {
    buildingList.add(new Buildings());
  }
}

最后是我的 UFO 课(创建飞过的 UFO):

And finally my UFO class (creates the UFO flying by):

import java.awt.*;
import javax.swing.*;
public class UFO extends JPanel
{
  private int x = 20; //x and y coordinates of the ball
  private int y = 20;
  private int xa = 1;
  public void move() //Increase both the x and y coordinates
  {
    if (x + xa < 0) {
      xa = 1;
    }
    if (x + xa > 784-75) 
    {
      xa = -1;
    }
    x = x + xa; 
  }
  public void paint(Graphics g)
  {
    super.paint(g); //Clears the panel, for a fresh start
    Graphics2D g2d = (Graphics2D) g;
    g2d.setColor(Color.LIGHT_GRAY);
    g2d.fillOval(x,y,75,25); //Draw the ball at the desired point
  }
}

推荐答案

因此,每次调用 Buildings#paint 时,它都会重新生成所有构建,这是随机完成的.

So, every time Buildings#paint is called, it regenerates all the builds, which is done randomly.

public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;

    Color transYellow = new Color(255, 255, 0, 59);

    g2d.setColor(Color.BLACK);
    g2d.fillRect(0, 0, maxX, maxY);

    g2d.setColor(Color.WHITE);
    g2d.fillRect(5, 5, 25, 25);

    int a = 0;

    for (int i = 10; i < 634; i += (a + 10))//buildings
    {

        g2d.setColor(Color.GRAY);
        g2d.drawRect(i, maxY - height, width, height);
        g2d.fillRect(i, maxY - height, width, height);

        rows = Math.round((height) / 25);
        columns = Math.round(width / 25);

        for (int j = 1; j <= columns; j++)//windows
        {
            for (int k = 1; k <= rows; k++) {
                g2d.setColor(Color.BLACK);
                g2d.drawRect(i + 5 * j + 20 * (j - 1), (maxY - height) + 5 * k + 20 * (k - 1), 20, 20);
                if (Math.random() < 0.7) {
                    g2d.setColor(Color.YELLOW);
                    g2d.fillRect(i + 5 * j + 20 * (j - 1), (maxY - height) + 5 * k + 20 * (k - 1), 20, 20);
                } else {
                    g2d.setColor(Color.BLACK);
                    g2d.fillRect(i + 5 * j + 20 * (j - 1), (maxY - height) + 5 * k + 20 * (k - 1), 20, 20);
                    g2d.setColor(transYellow);
                    g2d.fillRect(i + 5 * j + 20 * (j - 1), (maxY - height) + 5 * k + 20 * (k - 1), 20, 20);
                }
            }
        }
        addBuilding();
        a = width;
        height = (int) (Math.random() * 462 + 100);
        width = (int) (Math.random() * 100 + 100);

    }
}

有两种方法可以解决这个问题,您使用哪种方法取决于您想要实现的目标.您可以将建筑物直接渲染到 BufferedImage 并在每个绘制周期简单地绘制它,或者您可以缓存您需要的信息以重新创建建筑物.

There's two ways you might be able to solve this, which you use will depend on what you want to achieve. You could render the buildings directly to a BufferedImage and simply paint that on each paint cycle or you could cache the information you need in order to re-create the buildings.

BufferedImage 方法更快,但不能动画,所以如果你想以某种方式动画建筑物(使灯光闪烁),你需要建立一系列允许您简单地重新绘制它们的信息.

The BufferedImage approach is quicker, but can't be animated, so if you want to animate the buildings in some way (make the lights flicker), you will need to build up a series of information which allows you to simply repaint them.

我要说第二个,因为您已经询问了从 ArrayList 绘制资产的问题.

I'm going for the second, as you've asked about painting assets from a ArrayList.

我首先将您的绘画"代码翻译成虚拟建筑的单一概念,其中还包含有关其自身灯光的信息.

I started by translating your "paint" code into a single concept of a virtual building, which has also has information about it's own lights.

public class Building {

    protected static final Color TRANS_YELLOW = new Color(255, 255, 0, 59);

    private int x, y, width, height;
    private List<Light> lights;

    public Building(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;

        lights = new ArrayList<>(25);
        int rows = Math.round((height) / 25);
        int columns = Math.round(width / 25);

        for (int j = 1; j <= columns; j++)//windows
        {
            for (int k = 1; k <= rows; k++) {
                Color color = null;
                if (Math.random() < 0.7) {
                    color = Color.YELLOW;
                } else {
                    color = TRANS_YELLOW;
                }
                lights.add(new Light(x + 5 * j + 20 * (j - 1), y + 5 * k + 20 * (k - 1), color));
            }
        }
    }

    public void paint(Graphics2D g2d) {
        g2d.setColor(Color.GRAY);
        g2d.drawRect(x, y, width, height);
        g2d.fillRect(x, y, width, height);
        for (Light light : lights) {
            light.paint(g2d);
        }
    }

    public class Light {

        private int x, y;
        private Color color;

        public Light(int x, int y, Color color) {
            this.x = x;
            this.y = y;
            this.color = color;
        }

        public void paint(Graphics2D g2d) {
            g2d.setColor(Color.BLACK);
            g2d.fillRect(x, y, 20, 20);
            g2d.setColor(color);
            g2d.fillRect(x, y, 20, 20);
        }
    }

}

这允许您为 Building 生成主要参数并简单缓存结果,并在需要时简单地绘制它.

This allows you to generate the primary parameters for the Building and simple cache the results and when needed, simply paint it.

例如...

public class Buildings {

    private int maxX = 784;
    private int maxY = 712;

    private List<Building> buildings;

    public Buildings() {
        buildings = new ArrayList<>(25);
        for (int i = 10; i < 634; i += 10)//buildings
        {
            int width = (int) (Math.random() * 100 + 100);
            int height = (int) (Math.random() * 350 + 100);
            int x = i;
            int y = maxY - height;

            buildings.add(new Building(x, y, width, height));
        }
    }

    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        for (Building building : buildings) {
            building.paint(g2d);
        }
    }
}

我还更改了您的 UFO 类,使其不再从 JPanel 扩展,因为它只是不需要并且可能是您的绘画混淆的主要原因.

I also changed your UFO class so it no longer extends from JPanel, as it just doesn't need to and is probably the primary cause of confusion with your painting.

然后我在您的 CityScape 中更新了您的 paint 方法以使用 paintComponent 代替...

I then updated your paint method in your CityScape to use paintComponent instead...

public class CityScape extends JPanel {

    Buildings a = new Buildings();
    UFO b = new UFO();

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        a.paint(g);
        b.paint(g);
    }

作为一个可运行的例子...

As a runnable example...

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

public class CityScape extends JPanel {

    Buildings a = new Buildings();
    UFO b = new UFO();

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
        a.paint(g);
        b.paint(g);
    }

    public void move() {
        b.move();
    }

    public static void main(String[] args) throws InterruptedException {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Frame");
                CityScape jpe = new CityScape();
                frame.add(jpe);
                frame.setSize(800, 750);
                frame.setBackground(Color.BLACK);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                System.out.println(frame.getContentPane().getSize());

                Timer timer = new Timer(10, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        jpe.move(); //Updates the coordinates
                        jpe.repaint(); //Calls the paint method
                    }
                });
                timer.start();
            }
        });
    }

    public class Buildings {

        private int maxX = 784;
        private int maxY = 712;

        private List<Building> buildings;

        public Buildings() {
            buildings = new ArrayList<>(25);
            for (int i = 10; i < 634; i += 10)//buildings
            {
                int width = (int) (Math.random() * 100 + 100);
                int height = (int) (Math.random() * 350 + 100);
                int x = i;
                int y = maxY - height;

                buildings.add(new Building(x, y, width, height));
            }
        }

        public void paint(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;
            for (Building building : buildings) {
                building.paint(g2d);
            }
        }
    }

    public static class Building {

        protected static final Color TRANS_YELLOW = new Color(255, 255, 0, 59);

        private int x, y, width, height;
        private List<Light> lights;

        public Building(int x, int y, int width, int height) {
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;

            lights = new ArrayList<>(25);
            int rows = Math.round((height) / 25);
            int columns = Math.round(width / 25);

            for (int j = 1; j <= columns; j++)//windows
            {
                for (int k = 1; k <= rows; k++) {
                    Color color = null;
                    if (Math.random() < 0.7) {
                        color = Color.YELLOW;
                    } else {
                        color = TRANS_YELLOW;
                    }
                    lights.add(new Light(x + 5 * j + 20 * (j - 1), y + 5 * k + 20 * (k - 1), color));
                }
            }
        }

        public void paint(Graphics2D g2d) {
            g2d.setColor(Color.GRAY);
            g2d.drawRect(x, y, width, height);
            g2d.fillRect(x, y, width, height);
            for (Light light : lights) {
                light.paint(g2d);
            }
        }

        public class Light {

            private int x, y;
            private Color color;

            public Light(int x, int y, Color color) {
                this.x = x;
                this.y = y;
                this.color = color;
            }

            public void paint(Graphics2D g2d) {
                g2d.setColor(Color.BLACK);
                g2d.fillRect(x, y, 20, 20);
                g2d.setColor(color);
                g2d.fillRect(x, y, 20, 20);
            }
        }

    }

    public class UFO {

        private int x = 20; //x and y coordinates of the ball
        private int y = 20;
        private int xa = 1;

        public void move() //Increase both the x and y coordinates
        {
            if (x + xa < 0) {
                xa = 1;
            }
            if (x + xa > 784 - 75) {
                xa = -1;
            }
            x = x + xa;
        }

        public void paint(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;
            g2d.setColor(Color.LIGHT_GRAY);
            g2d.fillOval(x, y, 75, 25); //Draw the ball at the desired point
        }
    }
}

这篇关于从 ArrayList 重新绘制类的实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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