-1

I have read a lot of answers about this problem but I can't manage to find my error even on a simple code. Here is the problem : I'd like to draw an Image in a JLabel which is in a JPanel, but the paintComponent() method of the JLabel isn't called.

Here is the code :

The ImagePainter class should draw an image

public class ImagePainter extends JLabel{
    private Image image;

    public ImagePainter(){
        try {
            image = ImageIO.read(new File("src/testgui/image.png"));
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(image, 0, 0, null);
        System.out.println("in paintComponent");
    }
}

Here is a standard JFrame. I took care to add the JPanel to the contentPane

public class Display extends JFrame{

    public Display(){
        JPanel jp = new JPanel();
        ImagePainter i = new ImagePainter();

        getContentPane().add(jp);
        jp.add(i);
        jp.repaint();

        setSize(800, 800);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }
}

And finally the main. I instanciate Display on the EDT like everyone tell to do :

public class Main {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable(){
            @Override
            public void run(){
                Display d = new Display();
            }
        });
    }

}

Finally, I observed that if I directly add the ImagePainter to the contentPane, the image is drawn correctly. It's probably a stupid error but I spend literally hours trying to find it and really can't see it. Thank you in advance !

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Alsvartr
  • 3
  • 2
  • 1) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). (Put the `main` method in the `Display` class to educe it to just 2 classes, then demote `ImagePainter` from `public` to default access and paste it into the end.) 2) One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). – Andrew Thompson Feb 25 '17 at 18:57

2 Answers2

2

The label does not account for the preferred size of the image when the image is custom painted! The panel by default has a flow layout. A flow layout does not stretch components to fit. So that label would have size of 0 x 0 pixels. You can confirm that by adding a visible border to the label.

But given the image is displayed in a label, why not just set the image as the icon of the label?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • Ok thank you ! So I only need to change the layout manager, and what kind of layout manager will make it work ? – Alsvartr Feb 25 '17 at 18:58
  • First I want to understand why the code is custom painting a label. Why do that? – Andrew Thompson Feb 25 '17 at 18:58
  • BTW - setting a different layout for the panel is not the best way to fix it, even if custom painting the label makes sense. – Andrew Thompson Feb 25 '17 at 19:00
  • Ok I see, but I need to transform my image in response to mouse events, so I don't know if it is a good idea to set the image as the icon of the label but I didn't know that was possible so I will learn what I can do with that. – Alsvartr Feb 25 '17 at 19:05
  • *"..transform my image.."* How? Please add lots more details of the transformations that need to be done. – Andrew Thompson Feb 25 '17 at 19:07
  • Ok so I'm doing a pool game, the image I want to display is the cue. The transformation I intend to do is translate it and rotate it – Alsvartr Feb 25 '17 at 19:10
  • OK.. I'd avoid the label completely and just custom paint the panel. Override the `getPreferredSize()` method of the panel to return a rectangular size in the shape of the table. Then after painting the pool table surface, rotate or transform the graphics instance to paint the cue. – Andrew Thompson Feb 25 '17 at 19:13
  • 1
    Thanks a lot I'll try that ! – Alsvartr Feb 25 '17 at 19:18
0

Also, the jp.repaint() statement in the Display constructor is useless, since you have not yet set the frame visible.

FredK
  • 4,094
  • 1
  • 9
  • 11