tags:

views:

34

answers:

2

Hi chaps, I think I'm being a bit of an idiot, given that I haven't done Swing programming in a while, but I'm trying to draw a simple image to screen, and I'm not getting what I expected

public class ImageApp {

    public static void main(String[] args) throws MalformedURLException, IOException {
        final Image image = ImageIO.read(new File("/Library/WebServer/Documents/image.gif"));

        final JPanel component = new JPanel(){

            public void paint(final Graphics g) {
                System.out.println("Drawing image "+image.getWidth(null)+" "+image.getHeight(null));
                g.drawString("hello", 0,0);
                g.drawImage(image,this.getWidth()/2,this.getHeight()/2, 100, 100, Color.blue,this);
                super.paint(g);
            }
        };

        final JFrame frame = new JFrame();

        frame.add(component);
        frame.setSize(100, 100);

        frame.pack();
        frame.setVisible(true);
    }

}

This renders a blank window which doesn't seem to be sized to 100,100. Is there some other step I need to perform to get the graphics to appear on screen, or the size to be respected?

I'm using JDK6 on OSX 10.6

+2  A: 

In Swing, you should override paintComponent(), not paint().

Addendum: e.g., see below. In a comment, @eugener raises an excellent point about using a JLabel as an alternative image container.

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ImageApp {

    public static void main(String[] args) throws IOException {
        final Image image = ImageIO.read(new File("image.jpg"));
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                final JPanel component = new JPanel() {

                    @Override
                    public void paintComponent(final Graphics g) {
                        g.drawImage(image, 0, 0, null);
                    }

                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(
                            image.getWidth(this), image.getHeight(this));
                    }
                };

                final JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(component);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}
trashgod
This doesn't seem to change the behaviour?
Ceilingfish
@Ceilingfish: I've revised your example; @rekin's example is also useful. Incidentally, always build on the EDT: http://download-llnw.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
trashgod
Thanks trashgod. The critical part here seems to be not calling `super.paintComponent` after rendering the image, or it overrides with the default "do nothing" behaviour!
Ceilingfish
Code in Your question calls `super.paint(g)` - which could introduce recursive call. It's always a good idea to call `super.paintComponent(g)`. Normally it draws only background which You can disable by calling `setOpaque(false)`. The swing drawing pipeline uses the flag to determine if it's necessary to draw underlying components. So to be most compliant (and avoid future redraw issues) it's best to call the super.
Rekin
@rekin: Good call on the recursion. @Ceilingfish: call `super.paintComponent(g)` _before_ you draw, as @rekin shows: http://java.sun.com/products/jfc/tsc/articles/painting/index.html
trashgod
@trashgod Why paint? Just use the JLabel - simpler IMO
eugener
@eugener: Good point; I've added a link to an example, which you should feel free to edit.
trashgod
+2  A: 

Try this:

public class ImageApp {

    public static void main(String[] args) throws MalformedURLException, IOException {
        final Image image = ImageIO.read(new File("/Library/WebServer/Documents/image.gif"));

        final JPanel component = new JPanel() {

            @Override
            public void paintComponent(final Graphics g) {
                super.paintComponent(g);
                System.out.println("Drawing image " + image.getWidth(null) + " " + image.getHeight(null));
                g.drawString("hello", 0,10);
                g.drawImage(image, this.getWidth() / 2, this.getHeight() / 2, 100, 100, Color.blue, this);
            }
        };

        final JFrame frame = new JFrame();

        frame.add(component);
        frame.setSize(100, 100);

        frame.setVisible(true);
    }
}
Rekin
Good example, although see my comment to @Ceilingfish. For comparison my example doesn't invoke `super.paintComponent(g)` because it fills the panel.
trashgod