Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display an images instantly in Java Applet?

I created a simple memory game in Java Applet. I have a problem with cards. Images need some extra load time during the first appearance. How to fix that? I need to show a image instantly after card flip.

I display loading screen until application isn't in AppStates.READY or AppStates.WAIT_FOR_START state but it dosen't help.

Memo.cs - main class with images loading

public class Memo extends JApplet {

    //...   

    public void init() {
        //...   
        try {
            SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { createGUI(); }});
        } 
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    private void createGUI() {
        final Model model = new Model(...);
        final View view = new View(model);

        getContentPane().add(view, BorderLayout.CENTER);
        setBackground(backgroundColor);
        setPreferredSize(new Dimension(width, height));

        model.setLoading(loadImages(loadingPath, format, 1));
        model.setCardsImages(loadImages(cardImagePath, format, 13));
        //...
        model.setAppState(AppStates.PROCESS);

        model.startNewGame();
        view.repaint();
    }

    private Image[] loadImages(String path1, String path2, int count) {
        Image[] imgs = new Image[count];        
        for(int i = 0; i < count; ++i) {
            imgs[i] = getImage(getCodeBase(), path1 + i + path2);
        }
        return imgs;
    }
}

Model.cs - hold images and application state, init board

public class Model {

    //...

    private AppStates appState;
    private Image[] cardsImages;

    public Model(...) {
        //...
        appState = AppStates.INIT;
    }

    public void startNewGame() {
        setAppState(AppStates.PROCESS);

        //... - init board - table with images' id

        setAppState(AppStates.WAIT_FOR_START);
    }

    public void setCardsImages(Image[] cardsImages) {
        this.cardsImages = cardsImages;
    }

    public Image getCardsImage(int v) {
        return cardsImages[v];
    }

    public AppStates getAppState() {
        return appState;
    }

    public void setAppState(AppStates appState) {
        this.appState = appState;
        //...
    }

    //...
}

View.cs - display board

public class View extends JPanel {

    //...

    private Model model;

    public View(Model model) {
        this.model = model;
        //...
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        if(model != null) {
            switch (model.getAppState()) {

            //...

            case WAIT_FOR_START:            
            case READY:
                //...
                drawBoard(g2d, model.getBoard(), model.getStates(), model.getFrontTypes());
                break;

            }
        }
        repaint();
    }

    private void drawBoard(Graphics2D g2d, int[][] board, int[][] states, int[][] frontTypes) {
        if(board != null && states != null && board.length > 0 && states.length > 0) {
            for(int x = 0; x < board.length; x++) {
                for(int y = 0; y < board[x].length; y++) {  
                    if(states[x][y] != Model.HIDE) {
                        Image img = null;

                        //...
                        img = model.getCardsImage(board[x][y]);

                        g2d.drawImage(
                                img,
                                model.getFirstCardX() + x * model.getCardDistance() + x * model.getCardWidth(), 
                                model.getFirstCardY() + y * model.getCardDistance() + y * model.getCardHeight(), 
                                model.getCardWidth(), 
                                model.getCardHeight(),
                                null);

                        //...
                    }
                }
            }
        }
    }
}
like image 369
rebeliagamer Avatar asked Jan 17 '26 16:01

rebeliagamer


2 Answers

From the JavaDocs..

public Image getImage(URL url)

..

This method always returns immediately, whether or not the image exists. When this applet attempts to draw the image on the screen, the data will be loaded.

Use ImageIO.read(URL) instead. This method will 'block' (it will stop at that code line) until the image is read. So when the app. goes to use the image, it has already been completely loaded.

Another way to get around the problem (not quite the way you wanted) is to change..

g2d.drawImage(
    img,
    model.getFirstCardX() + x * model.getCardDistance() + x * model.getCardWidth(), 
    model.getFirstCardY() + y * model.getCardDistance() + y * model.getCardHeight(), 
    model.getCardWidth(), 
    model.getCardHeight(),
    null);

To..

g2d.drawImage(
    img,
    model.getFirstCardX() + x * model.getCardDistance() + x * model.getCardWidth(), 
    model.getFirstCardY() + y * model.getCardDistance() + y * model.getCardHeight(), 
    model.getCardWidth(), 
    model.getCardHeight(),
    this);

If the image is loaded asynchronously (e.g. using Applet.getImage(URL)) the GUI will be notified to repaint as more becomes available.

like image 168
Andrew Thompson Avatar answered Jan 20 '26 07:01

Andrew Thompson


you can take the advantage of double buffering in Swing and displaying at once when everything is ready.

If you need to do it inbetween you can keep a pre-developed copy and displaying it when required.

like image 34
Naveen Avatar answered Jan 20 '26 08:01

Naveen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!