-1

I'm making a game/simulator and I'm using the following method to load an Image into my current Java project:

public static Image getImage(String name) {
    URL url = ImageLoader.class.getClassLoader().getResource("resources/" + name);
    Image img = Toolkit.getDefaultToolkit().createImage(url);
    ImageLoader.tracker.addImage(img, 1);
    try {
        ImageLoader.tracker.waitForID(1);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return img;
}

This loads the images into my class that is drawing all items including the player (who has 4 different images for each direction he can face: north, south, east, west):

private Image player = ImageLoader.getImage("playerEast.png");
private Image playerEast = ImageLoader.getImage("playerEast.png");
private Image playerWest = ImageLoader.getImage("playerWest.png");
private Image playerSouth = ImageLoader.getImage("playerSouth.png");
private Image playerNorth = ImageLoader.getImage("playerNorth.png");

The class that loads above images paints them in the area like such:

public class TerritoryPanel extends JPanel implements Observer {
@Override
protected void paintComponent(Graphics g){
    super.paintComponent(g);
//Draw player
    g.drawImage(player, (x, y, this);

}

I'm trying to update the pics with this method in the same class:

public void rotateEast(){
    player = playerEast;
    repaint();
    revalidate();
}

..but just calling this rotateEast() does not update the picture immediately, it only gets updated afterwards when my regular Observer update() cycle calls repaint(), this happens every second so the missing repaint of rotateEast is visible:

@Override
public void update(Observable o, Object arg) {
    if (EventQueue.isDispatchThread()) {
        this.repaint();
    } else { // Simulation-Thread
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                repaint();
            }
        });
    }
}

Why does the repaint() from rotateEast seem to have no effect? Thank you very much in forward

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
fasoh
  • 504
  • 4
  • 17
  • 1
    It could a threading issue, where the variable `player` is been updated by another thread and the change isn't been reflected in other threads yet. It could be you have a long running process which is blocking the Event Dispatching Thread. It could be that you've saturated the EDT with updates and it's taking time for it to clear. Consider providing a [runnable example](https://stackoverflow.com/help/mcve) which demonstrates your problem. This will result in less confusion and better responses – MadProgrammer Jan 14 '15 at 21:33
  • 1
    I'd also discourage the use of `createImage` in favour of `ImageIO.read`. See [Reading/Loading an Image](http://docs.oracle.com/javase/tutorial/2d/images/loadimage.html) for more details. It will do the same job your current code is trying to do, but it will also throw an exception if the image can't be loaded – MadProgrammer Jan 14 '15 at 21:34
  • One way to get images for the runnable example mentioned above by @MadProgrammer, is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). Oh, and `g.drawImage(player, (x, y, this);` would not compile due to unmatched brackets.. – Andrew Thompson Jan 14 '15 at 23:29

1 Answers1

0

but just calling this rotateEast() does not update the picture immediately, it only gets updated afterwards when my regular Observer update() cycle calls repaint(),

Don't know if it will make a difference but the normal logic is:

revalidate(); // to invoke the layout manager
repaint(); // to repaint all the components

Even if it doesn't make a difference in this case this order you should always use when dynamically changing the property of a component including adding/remove components from a panel.

camickr
  • 321,443
  • 19
  • 166
  • 288