Java读取并加载图像

标签 java image load

我刚刚完成扫雷游戏的制作,除了一件事之外,一切功能都很完美,即将图像加载到游戏中的速度。我注意到,如果游戏中有大量单元格,则鼠标单击单元格后图像加载速度会非常慢,如果单元格数量较少,加载速度会更快。有没有其他方法可以使加载图像比我使用的方法快得多?这是我用来将图像加载到游戏中的方法:

   private void draw(Graphics g) {
        BufferedImage gRec =null, flag=null, mine=null, aCount0=null,
            aCount1=null,aCount2 =null,aCount3 =null,aCount4 =null,aCount5 =null,
            aCount6 =null,aCount7 =null,aCount8 = null;
        try {
           gRec = ImageIO.read(new File("/Users/msa_666/Desktop/blank.gif"));
                flag = ImageIO.read(new File("/Users/msa_666/Desktop/bombflagged.gif"));
                mine = ImageIO.read(new File("/Users/msa_666/Desktop/bombdeath.gif"));
                flag = ImageIO.read(new File("/Users/msa_666/Desktop/bombflagged.gif"));
                aCount0 = ImageIO.read(new File("/Users/msa_666/Desktop/open0.gif"));
                aCount1 = ImageIO.read(new File("/Users/msa_666/Desktop/open1.gif"));
                aCount2 = ImageIO.read(new File("/Users/msa_666/Desktop/open2.gif"));
                aCount3 = ImageIO.read(new File("/Users/msa_666/Desktop/open3.gif"));
                aCount4 = ImageIO.read(new File("/Users/msa_666/Desktop/open4.gif"));
                aCount5 = ImageIO.read(new File("/Users/msa_666/Desktop/open5.gif"));
                aCount6 = ImageIO.read(new File("/Users/msa_666/Desktop/open6.gif"));
                aCount7 = ImageIO.read(new File("/Users/msa_666/Desktop/open7.gif"));
                aCount8 = ImageIO.read(new File("/Users/msa_666/Desktop/open8.gif"));
                }
                 catch (IOException e) { 
              e.printStackTrace();
           } 


        if (getCovered() == true && getMarked () == false) {    // gray rectangle
           g.drawImage(gRec,getX(),getY(),w,h,null);

        }
        else if (getCovered()==true && getMarked() ==  true) {  //flag
           g.drawImage(flag,getX(),getY(),w,h,null);

        }
        else if (getCovered()== false && getMined()== true){        //mine
           g.drawImage(mine,getX(),getY(),w,h,null);

        }
        else if ( getCovered() == false && getMined() == false) {   // adjacency count image
            switch (getAdjCount()){
                case 0:
           g.drawImage(aCount0,getX(),getY(),w,h,null);
                break;
                case 1:
           g.drawImage(aCount1,getX(),getY(),w,h,null);
                break;
                case 2:
           g.drawImage(aCount2,getX(),getY(),w,h,null);
                break;
                case 3:
           g.drawImage(aCount3,getX(),getY(),w,h,null);
                break;

                case 4:
           g.drawImage(aCount4,getX(),getY(),w,h,null);
                break;
                case 5:
           g.drawImage(aCount5,getX(),getY(),w,h,null);
                break;
                case 6:
           g.drawImage(aCount6,getX(),getY(),w,h,null);
                break;
                case 7:
           g.drawImage(aCount7,getX(),getY(),w,h,null);
                break;
                case 8:
           g.drawImage(aCount8,getX(),getY(),w,h,null);
                break;


        }
     }
    }

这是单击每个单元格后重新绘制每个单元格的鼠标监听器:

   public void mouseClicked(MouseEvent e) {
      int sRow, sCol;
      sRow= e.getX() / cellHeight;
      sCol = e.getY()/ cellWidth;
      System.out.println(e.getX() +"," +sCol);
      System.out.println(e.getY()+","+sRow);
      if (e.getButton() == MouseEvent.BUTTON1) {
        if( cells[sRow][sCol].getMarked() == false)     
           uncoverCell(cells[sRow][sCol]);
          // cells[sRow][sCol].setCovered(false);
        System.out.println(cells[sRow][sCol].getMined());
        repaint();
     }
     else if (e.getButton() == MouseEvent.BUTTON2) {
     }
     else if (e.getButton() == MouseEvent.BUTTON3) {
        if (cells[sRow][sCol].getMarked() == false){
           cells[sRow][sCol].setMarked(true);
                       repaint();

        }
        else {
           cells[sRow][sCol].setMarked(false);          
           repaint();           
        }
     }

     if (allMinesMarked() && allNonMinesUncovered()){
        System.out.println("You Win");
     }
  }


  public void paintComponent(Graphics g) { 
     for ( int i=0 ; i <rowCount; i++ ) {
        for (int j=0; j<columnCount; j++) {
           cells[i][j].draw(g);
        }
     }

  }

最佳答案

您需要告诉我们:

  • draw(...) 是在哪里调用的?
  • 如何获取传递到绘制方法参数中的 Graphics 对象 g?

我在这里猜测是因为我们没有所有相关代码,但看起来好像您每次想要显示图像时都在重新阅读图像。如果是这样,请不要这样做。在程序开始时仅读取图像一次,然后使用图像,或者更好的是,在需要时获取图像图标。

编辑
感谢您发布更多代码,这实际上证实了我的怀疑:每次重新绘制 GUI 时,您都会重新读取图像文件。这是非常低效的,并且会使你的程序变得缓慢。同样,您应该将图像读入您的程序一次,然后多次使用它们。

我自己会从图像创建 ImageIcons,然后将它们显示在 JLabel 中。当需要交换图像时,只需在 JLabel 上调用 setIcon(...) 即可。这样就不需要搞乱 paintComponent(...)

编辑2
例如(编译并运行它):

import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.*;

public class SwapIcons {
   private static final int CELL_SIDE_COUNT = 3;
   private ImageCell[] imageCells = new ImageCell[CELL_SIDE_COUNT * CELL_SIDE_COUNT];
   private JPanel mainPanel = new JPanel();

   public SwapIcons(final GetImages getImages) {
      mainPanel.setLayout(new GridLayout(CELL_SIDE_COUNT, CELL_SIDE_COUNT));
      mainPanel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));

      for (int i = 0; i < imageCells.length; i++) {
         imageCells[i] = new ImageCell(getImages);
         mainPanel.add(imageCells[i].getImgLabel());
      }
   }

   public JComponent getMainComponent() {
      return mainPanel;
   }

   private static void createAndShowGui(GetImages getImages) {
      SwapIcons swapIcons = new SwapIcons(getImages);

      JFrame frame = new JFrame("Click on Icons to Change");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(swapIcons.getMainComponent());
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      try {
         final GetImages getImages = new GetImages();
         SwingUtilities.invokeLater(new Runnable() {
            public void run() {
               createAndShowGui(getImages);
            }
         });
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

class ImageCell {
   private JLabel imgLabel = new JLabel();
   private GetImages getImages;
   private int iconIndex = 0;

   public ImageCell(final GetImages getImages) {
      this.getImages = getImages;
      imgLabel.setIcon(getImages.getIcon(0));
      imgLabel.addMouseListener(new MyMouseListener());
   }

   public JLabel getImgLabel() {
      return imgLabel;
   }

   private class MyMouseListener extends MouseAdapter {
      @Override
      public void mousePressed(MouseEvent e) {
         iconIndex++;
         iconIndex %= getImages.getIconListSize();
         imgLabel.setIcon(getImages.getIcon(iconIndex));
      }
   }
}

// Simply gets a SpriteSheet and subdivides it into a List of ImageIcons
class GetImages {
   private static final String SPRITE_PATH = "http://th02.deviantart.net/"
         + "fs70/PRE/i/2011/169/0/8/blue_player_sprite_sheet_by_resetado-d3j7zba.png";
   public static final int SPRITE_ROWS = 6;
   public static final int SPRITE_COLS = 6;
   public static final int SPRITE_CELLS = 35;

   private List<ImageIcon> iconList = new ArrayList<ImageIcon>();

   public GetImages() throws IOException {
      URL imgUrl = new URL(SPRITE_PATH);
      BufferedImage mainImage = ImageIO.read(imgUrl);

      for (int i = 0; i < SPRITE_CELLS; i++) {
         int row = i / SPRITE_COLS;
         int col = i % SPRITE_COLS;
         int x = (int) (((double) mainImage.getWidth() * col) / SPRITE_COLS);
         int y = (int) ((double) (mainImage.getHeight() * row) / SPRITE_ROWS);
         int w = (int) ((double) mainImage.getWidth() / SPRITE_COLS);
         int h = (int) ((double) mainImage.getHeight() / SPRITE_ROWS);
         BufferedImage img = mainImage.getSubimage(x, y, w, h);
         ImageIcon icon = new ImageIcon(img);
         iconList.add(icon);
      }
   }

   // get the Icon from the List at index position
   public ImageIcon getIcon(int index) {
      if (index < 0 || index >= iconList.size()) {
         throw new ArrayIndexOutOfBoundsException(index);
      }

      return iconList.get(index);
   }

   public int getIconListSize() {
      return iconList.size();
   }

}

关于Java读取并加载图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15718536/

相关文章:

Java 扫描仪从第二次开始工作

c++ - 使用 Pleora SDK 保存缓冲区会得到蓝色、双倍的 BMP,下方有灰色条

html - 如何使用CSS同时更改悬停的元素和另一个div

jquery - 我想从链接将不同的图像加载到一个 div

javascript - 从书签加载外部 JS?

java - 如何让 Hibernate JPA 自动管理列表索引?

java - Jmeter beanshell Sampler_调用 bsh 方法时出错

java - 包括来自外部java文件的面板?

css - CSS 中的 Webpack 文件加载器和图像

android - 在 xamarin (c#) 中加载嵌入式 xml