6

I recently read this thread (Creating a custom button in Java) on creating custom buttons in java by extending the JButton class, however all the solutions on this thread use graphics drawn in java.

I wanted to have my button based on a button image I had drawn in photoshop. So I tried to apply what I read in that thread with this result:

import javax.swing.*;
import java.awt.*;

public class nextButton extends JButton {
    @Override
        protected void paintComponent(Graphics g) {
        Image image = new ImageIcon("nextButton.png").getImage();
        g.drawImage(image,0,0,this);
}

    @Override
    public Dimension getPreferredSize() {
        Dimension size = super.getPreferredSize();
        size.setSize(75, 150);
        return size;
    }
}

When I run the main program having added this button to a JPanel it doesn't display. I am assuming it could be one of several reasons:

a) The size of the JButton doesn't match the image? b) I haven't loaded the image properly. In the notes my lecturer gave me he writes out the display image code with just "imageName.png" with no file path so I have no idea if this is the correct way to do it, or how the program will know to load the image. c) Something else which is beyond my knowledge so far.

If anyone knows how to solve this I'd be very grateful.

Thanks so much!

Community
  • 1
  • 1
user1060899
  • 91
  • 1
  • 2
  • 5
  • a couple of comments, more or less unrelated to your problem: a) the paintComponent override is illegal b) never-ever _change_ anything in a getter c) in particular, setSize is done by the LayoutManager anyway, will have no effect in a sane application d) it is correct to override getPreferredSize and return a reasonable sizing hint, based on the internals of the component, here that could be the size of the image e) dont re-load the image in paint (no heavy lifting ever in the paint cycle!), instead load it once at construction time – kleopatra Nov 23 '11 at 10:19
  • btw, please learn java naming conventions and stick to them – kleopatra Nov 23 '11 at 10:20

3 Answers3

6

I asked this question earlier as well. The solution I found worked best was actually doing this, instead of drawing.

ImageIcon icon = new ImageIcon("pathOfImageHere.png");
JButton button = new JButton(icon);

So that sets the button to the image. Now what I chose to do was make the button invisible and remove all the borders. So I did this next:

button.setOpaque(false);
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.setFocusPainted(false);
Van-Sama
  • 1,154
  • 4
  • 14
  • 21
  • Morevoer, we can define different button states images (see : [link](http://www.leepoint.net/notes-java/GUI/components/20buttons/23buttonicons.html)). Your solution with that trick worked perfectly! – Alexxx May 22 '13 at 09:29
4

For one, you should use ImageIO.read(new File("somefile.png")) to load an Image. Note that if there is no absolute path specified, it default to relative from the working directory. If you're running out of eclipse, it's the project folder. Out of a jar, it's the folder the jar is in (unless otherwise specified).

See http://docs.oracle.com/javase/tutorial/2d/images/loadimage.html for an explanation of how to load an image correctly (also says how to do it from within an applet).

Also, you should load the image once, then reuse it for each paint iteration:

BufferedImage image;

public nextButton() {
    try {
        image = ImageIO.read(new File("nextButton.png"));
    } catch (IOException e) {
        e.printStackTrace();
    }
}

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

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

Let me know if this works for you (make sure to put your png in the working directory!).

jli
  • 6,523
  • 2
  • 29
  • 37
  • a) don't use setXXSize, instead override getPreferredSize (you are subclassing already, no excuse to be sloppy ;-) b) the paintComponent override is illegal, it _must_ be implemented to comply to its opacity contract – kleopatra Nov 23 '11 at 10:12
  • -1 ahhh ... just saw your edit, that's simply wrong: overriding getPref _certainly_ is the way to go. – kleopatra Nov 23 '11 at 10:15
  • @kleopatra ah sorry about that, I guess I had it wrong. Fixed it with an edit. I'm too used to working with hacked together Swing stuff, I'll keep that note about the setSize thing in mind. The lack of `super.paintComponent` was a mistake on my part that I do know is incorrect, so I fixed that as well. – jli Nov 23 '11 at 19:27
3

Why don't you just use the JButton constructor that takes an Image?

http://www.apl.jhu.edu/~hall/java/Swing-Tutorial/Swing-Tutorial-JButton.html

Eric Rosenberg
  • 1,543
  • 9
  • 18