2016-03-13 99 views
0

我目前正在尝试了解更多关于绘画在swing中的信息,并且我正在创建一个小游戏,但我似乎被卡住了。我试图给ArrayList添加几个矩形(敌人),然后在paintComponent()方法中绘制它们,但它似乎不起作用。无法在JPanel上绘制矩形

这里是我的敌人类

import utils.RandomUtils; 

import java.awt.*; 
import java.awt.geom.Rectangle2D; 

public class Enemy 
{ 
    double x, y, w, h; 
    Shape enemy; 

    Toolkit tk = Toolkit.getDefaultToolkit(); 
    double width = tk.getScreenSize().width; 
    double height = tk.getScreenSize().height; 

    RandomUtils utils = new RandomUtils(); 

    public Enemy(int w, int h) 
    { 
     this.w = w; 
     this.h = h; 

     enemy = new Rectangle2D.Double(setX(), setY(), w, h); 
    } 

    private double setX() 
    { 
     return x = utils.randInt((int) w, (int) width); 
    } 

    private double setY() 
    { 
     return y = utils.randInt((int) h, (int) height); 
    } 

    public Shape getEnemy() 
    { 
     return enemy; 
    } 
} 

这是我局级

import players.Enemy; 

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.util.ArrayList; 

public class Board extends JPanel 
{ 
    int x, y, speed = 1, height = 25, width = 25; 

    public Board() 
    { 
     addControls(); 
    } 

    public void addControls() 
    { 
     Action upAction = new AbstractAction() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       y = y - speed; 
       repaint(); 
      } 
     }; 

     getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke("W"), "Up Action"); 
     getActionMap().put("Up Action", upAction); 

     Action downAction = new AbstractAction() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       y = y + speed; 
       repaint(); 
      } 
     }; 

     getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke("S"), "Down Action"); 
     getActionMap().put("Down Action", downAction); 

     Action leftAction = new AbstractAction() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       x = x - speed; 
       repaint(); 
      } 
     }; 

     getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke("A"), "Left Action"); 
     getActionMap().put("Left Action", leftAction); 

     Action rightAction = new AbstractAction() 
     { 
      @Override 
      public void actionPerformed(ActionEvent e) 
      { 
       x = x + speed; 
       repaint(); 
      } 
     }; 

     getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke("D"), "Right Action"); 
     getActionMap().put("Right Action", rightAction); 
    } 

    boolean enemiesDrawn = false; 
    java.util.List<Enemy> enemies = new ArrayList<>(); 
    java.util.List<Shape> enemyShapes = new ArrayList<>(); 

    public void setEnemies() 
    { 
     for(int enemyCount = 0; enemyCount < 15; enemyCount++) 
     { 
      System.out.println(enemyCount); 
      enemies.add(new Enemy(15, 15)); 
      enemyShapes.add(enemies.get(enemyCount).getEnemy()); 
     } 
    } 

    @Override 
    public void paintComponent(Graphics g) 
    { 
     super.paintComponent(g); 

     Graphics2D g2 = (Graphics2D) g; 

     g.setColor(Color.RED); 
     g.fillOval(x, y, width, height); 

     if(!enemiesDrawn) 
     { 
      setEnemies(); 

      g2.setColor(Color.BLUE); 
      g2.setBackground(Color.BLUE); 

      enemyShapes.forEach(g2::draw); 

      enemiesDrawn = true; 
     } 
    } 
} 

的Util类

import java.util.Random; 

public class RandomUtils 
{ 
    public RandomUtils() 
    { 
    } 

    public int randInt(int min, int max) 
    { 
     Random rand = new Random(); 
     return rand.nextInt((max - min) + 1) + min; 
    } 
} 

而且主类

import javax.swing.*; 

public class MainFrame 
{ 
    JFrame mainFrame; 

    public MainFrame() 
    { 
     mainFrame = new JFrame("Game"); 

     addComponents(); 

     mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH); 
     mainFrame.setLocationRelativeTo(null); 
     mainFrame.pack(); 
     mainFrame.setVisible(true); 
    } 

    public void addComponents() 
    { 
     mainFrame.add(new Board()); 
    } 

    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(MainFrame::new); 
    } 
} 

绘画椭圆形(玩家)的作品很好,我似乎无法吸引列表中的敌人。我应该做什么来解决这个问题?

+0

什么是有两个的ArrayList点的电流大小的敌人?考虑提供一个演示你的问题的可运行示例 – MadProgrammer

+0

一个用于敌人自己,另一个用于敌人的形状。我将发布完整的代码。 – Jonah

+1

侧面推荐,永远不要处理由JVM给您的Graphics对象'g2.dispose();'。只能处理您自己创建的图像或其他图形对象。这样做有可能破坏绘画链。 –

回答

2

所以你的主要问题是在这里...

if (!enemiesDrawn) { 
    setEnemies(); 

    g2.setColor(Color.BLUE); 
    g2.setBackground(Color.BLUE); 

    System.out.println("..."); 
    enemyShapes.forEach(g2::draw); 

    enemiesDrawn = true; 
} 

一旦paintComponent被调用一次,敌人将永远不会被涂一遍。 paintComponent可能会被调用很多次(通常是快速连续),每次调用时,都需要重新从零开始重新绘制组件的整个状态。

看一看Painting in AWT and SwingPerforming Custom Painting有关如何画秋千

观察工作的更多信息...

这是一种毫无意义的...

mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH); 
mainFrame.setLocationRelativeTo(null); 
mainFrame.pack(); 

你将框架设置为最大化,然后尝试打包它?这可能会导致某些系统出现问题,所以要小心。

RandomUtils应该创建的,因为它的工作原理,你正在运行有Random返回相同的值,在同一顺序的风险的方式Random一个实例。你可以只是摆脱单身

public enum RandomUtils { 

    INSTANCE; 

    private Random rand = new Random(); 

    public int randInt(int min, int max) { 
     return rand.nextInt((max - min) + 1) + min; 
    } 
} 

Enemy使用Toolkit是不是一个好主意,其实除了敌人应该有外面的世界知之甚少,Toolkit是不是最好的选择为了确定实际的可视屏幕尺寸,考虑到您的窗户有装饰物,而桌面上有任务栏等事物,这会冒着一些敌人出现在屏幕上的风险

由于您的程序工作方式,建议可以复制输出的东西很难。但基本上,您应该将所需的位置/大小传递给Enemy类的构造函数。

你可以使用一个ComponentListener和监控componentResized方法,它首先企稳,然后你可以创建一个基于组件

+0

啊,我明白了!感谢你的回答。它现在正在全面运转。 – Jonah