简体   繁体   中英

ImageIO.read preventing paintComponent from executing?

I am trying to a sprite image from a sprite mesh using BufferedImage and ImageIO. There is a separate class which handles the loading and storing of sprite images; this is where the problem seems to be. I load the sprite mesh into a BuffereImage using ImageIO, and for some reason this, intermittently, prevents paintComponent from being executed. When the program actually does load the program displays properly, however, the key listener stops working. I am using NetBeans 7.3 if that helps.

package breakout;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Random;

public class GamePanel extends JPanel implements Runnable {
    private Paddle paddle;
    private Breakout boRef;
    private Circle ball;
    private Graphics2D g2d, bufferedGraphics;
    private BufferedImage buffer;
    private Images images;
    private final int WIDTH = Constants.WINDOW_WIDTH;
    private final int HEIGHT = Constants.WINDOW_HEIGHT;
    private ArrayList<Block> blockList;
    private int numBlocks, blockRows, blockCols, ballXInc, ballYInc, blockPadding;
    private int totalWidth, blockX, blockY;
    private Thread ballThread;
    private boolean started, gameOver;
    private String gameOverText;
    private Random rand;

    public GamePanel( Breakout ref ) {
        boRef = ref;
        images = new Images();  <-- Problem

        numBlocks = 12;
        blockRows = 4;
        blockCols = 3;
        blockList = new ArrayList<>();
        blockY = 100;
        blockPadding = 5;
        totalWidth = ( blockCols * Block.WIDTH ) + ( ( blockCols - 1 ) * blockPadding );
        blockX = ( WIDTH / 2 ) - ( totalWidth / 2 ) - 60;
        setupBlocks();

        rand = new Random();        
        gameOverText = "";
        started = false;
        gameOver = false;

        buffer = new BufferedImage( WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB );
        bufferedGraphics = buffer.createGraphics();
        bufferedGraphics.setBackground( Color.LIGHT_GRAY );

        ball = new Circle( 250, 593, 6 );
        ball.setColor( Color.BLUE );
        ballThread = new Thread( this );
        ballXInc = 1;
        ballYInc = -1;

        paddle = new Paddle( this, 200, 600, 100, 15, Color.WHITE, Color.BLACK );

        addKeyListener( new KeyHandler() );
        setLayout( new BorderLayout() );
        setFocusable( true );
        requestFocus();
        System.out.println(" END" );
    }

private void setupBlocks() {
    int xPos = Block.WIDTH + blockPadding, yPos = Block.HEIGHT + blockPadding;
    int xInc = 1, yInc = 1;

    for( int y = 0; y < blockRows; ++y, yInc++ ) {
        for( int x = 0; x < blockCols; ++x, xInc++ ) {
            blockList.add( new Block( xPos * xInc + blockX, yPos * yInc + blockY ) );
        }

        xInc = 1;
    }
}

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

        bufferedGraphics.clearRect( 0, 0, WIDTH, HEIGHT );
       System.out.println( "HELLO" );

        //bufferedGraphics.drawImage( images.getImage(), 100, 100, images.getImage().getWidth(), images.getImage().getHeight(), null ); <-- DrawSprite

        if( !gameOver ) {
            for( Block b : blockList ) {
                b.draw( bufferedGraphics );
            }

            ball.draw( bufferedGraphics );
            paddle.draw( bufferedGraphics );
        } else { 
            bufferedGraphics.setFont( new Font( "Times New Roman", Font.BOLD, 48 ) );
            bufferedGraphics.drawString( gameOverText, WIDTH / 2 - 130, HEIGHT / 2); 
        }

        g2d.drawImage( buffer, 0, 0, WIDTH, HEIGHT, null );
    }

    private class KeyHandler extends KeyAdapter {
        @Override public void keyPressed( KeyEvent e ) {
            if( paddle.x - 10 > -10 && e.getKeyCode() == KeyEvent.VK_LEFT ) {
                paddle.x -= 10;

                if( !started ) {
                    ball.setX( ball.getX() - 10 );
                }
            } else if( paddle.x + paddle.width + 20 < WIDTH && e.getKeyCode() == KeyEvent.VK_RIGHT ) {
                paddle.x += 10;

                if( !started ) {
                    ball.setX( ball.getX() + 10 );
                }
            }

            if( e.getKeyCode() == KeyEvent.VK_SPACE ) {
                if( !started ) {
                    ballThread.start();
                    started = true;
                } else if( gameOver ) {
                    restart();
                }
            }


            repaint();
        }
    }
}



package breakout;

import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.awt.Rectangle;
import java.io.IOException;

public class Images {
    private BufferedImage texture, tex;
    private BufferedImage [] images;
    private String meshPath = "texture\\textures.png";
    private Raster imgRaster;
    private WritableRaster imgWritableRaster;

    public static final int TEX_WIDTH = 16;
    public static final int TEX_HEIGHT = 8;

    public Images() {
        images = new BufferedImage[1];

        try {
            texture = ImageIO.read( new File( meshPath ) ); <-- Seems to be the problem
        } catch( IOException e ) {
            System.out.println( e.getMessage() );
        }

        imgRaster = texture.getData( new Rectangle( TEX_WIDTH * 2, 0, TEX_WIDTH, TEX_HEIGHT ) );
        imgWritableRaster = imgRaster.createCompatibleWritableRaster();

        tex = new BufferedImage( texture.getColorModel(), imgWritableRaster, false, null );
        images[0] = tex;
    }

    public BufferedImage getImage() {
        return images[0];
    }
}

I load the sprite mesh into a BuffereImage using ImageIO, and for some reason this, intermittently, prevents paintComponent from being executed.

Intermittent problems of this nature suggests a possible threading conflict. I recommend that you do your ImageIO.read(...) call in a background thread such as that obtainable with a SwingWorker object.

Alternatively, you could read your images in on the main thread, and then start your GUI queued in the Swing Thread only after the images have all been read in. This is probably what I'd do.

public static void main(String[] args) {
  // read in images here in code that is *not* in a background thread

  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      // start GUI in here
    }
  });
}

When the program actually does load the program displays properly, however, the key listener stops working. I am using NetBeans 7.3 if that helps.

Don't use a KeyListener but rather use Key Bindings. The tutorials on this are pretty good, and also if you search this site, you'll see some examples on how to use this with animation. Some of the examples in fact have been written by me. For example:

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