1

Now this might sound very strange, which is also the reason I think it's a bug in Java itself.

I'm currently making custom components for my applications. These components (which extent JComponent) overwrite the paintComponent(); method. For some reason the frame appeared blank when any of these componenets was used as soon as I implemented images in the components, I did some debuggin and I found out the following: As soon as the code inside this overwritten method draws an image which was stored in a variable outside of the method itself, like a non-static class variable, the frame will appear blank when shown, until it's being resized. Everything works fine when using images stored in a variable in the paintComponent(); method itself. What happends here, and how am I able to solve this issue? I really need to use images stored in class variable to cache these images, otherwise it would be very performance intensive to load every image again and again.

Code similar to the folowing example works fine;

public class MyComponent extends JComponent {

    @Override
    public void paintComponenet(Graphics g) {
        Image img = ImageIO.read(getClass().getResource("/res/myImg.png"));
        g.drawImage(img, 0, 0, null);
    }
}

The frame appears blank when something like this is used;

public class MyComponent extends JComponent {

    private Image img = ImageIO.read(getClass().getResource("/res/myImg.png"));

    @Override
    public void paintComponenet(Graphics g) {
        g.drawImage(img, 0, 0, null);
    }
}

Loading the image (in the above example) inside the constructor or any other method won't have effect.

NOTE: The frame the components are used in isn't packed before (or after) it's being shown. This shouldn't make any sense though, because it works fine when using variables inside the paintComponent(); method itself.

royhowie
  • 11,075
  • 14
  • 50
  • 67
Tim Visée
  • 2,988
  • 4
  • 45
  • 55
  • I'm sorry, but I don't fully understand your answer. You are saying that the problem might be, that the image variable isn't `final`? I'll give that a try right now, it would still be strange though! NOTE: The frame isn't showing anything, neither native swing components as soon as these images are being used! – Tim Visée Nov 17 '13 at 23:37
  • Making this variable final, doesn't solve the problem, sadly. The same problem still occurs if I remove the draw call on the graphics object. So it's something with the code that's loading the images. – Tim Visée Nov 17 '13 at 23:42
  • Sorry, that's not it. Be sure that Swing GUI objects are constructed and manipulated _only_ on the [event dispatch thread](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html). – trashgod Nov 17 '13 at 23:42
  • 1- There is not size hint information, so it's likely that some layout managers will size the components to 0x0 on the screen. 2- It sounds like you are are calling `setVisible` on the screen BEFORE you add anything to it. – MadProgrammer Nov 17 '13 at 23:59
  • Those two points you made there are incorrect. The size is larger than 0x0. Secondly, `setVisible()` is the last method being called. – Tim Visée Nov 18 '13 at 00:03
  • @trashgod Thanks, this has fixed the problem. I put the code that initializes the frame inside an `invokeLater` block like so: `SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new TestFrame(); } });` – Tim Visée Nov 18 '13 at 00:05
  • @trashgod You should post your answer bellow, like I currently did, so I'm able to mark this question as answered. Thanks again, and have a nice day! – Tim Visée Nov 18 '13 at 00:10

1 Answers1

2

Answer by @trashgod


Be sure that Swing GUI objects are constructed and manipulated only on the event dispatch thread‌​.

For example, use the following code to initialize your frame that shows blank, this should solve your problem;

SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        new MyFrame();
    }
});
Community
  • 1
  • 1
Tim Visée
  • 2,988
  • 4
  • 45
  • 55