0

I am back again. I was wondering how I would go about placing a button on top of an image in a GUI. Here is my current code:

    private static JPanel titlePanel = new JPanel();
    private static JLabel titleScreen = new JLabel();
    private static JLabel titleScreenBackground = new JLabel();
    private static JButton startGameButton = new JButton("START GAME");
    private static ImageIcon titleScreenPic = new ImageIcon("http://icdn6.digitaltrends.com/image/battleship-650x0.jpg");
    private static JFrame frame=new JFrame(); //creates frame

    public static void main(String[] args) throws MalformedURLException{
            titleScreen();
    }

    public static void titleScreen() throws IOException{

        titleScreen.setLayout(new GridBagLayout());
        titlePanel.setLayout(new GridBagLayout());

        GridBagConstraints c1 = new GridBagConstraints();
        c1.gridx = 0;
        c1.gridy = 0;
        c1.anchor = GridBagConstraints.PAGE_END;

        titleScreenBackground.setIcon(titleScreenPic);

        titlePanel.add(startGameButton);

        titlePanel.setAlignmentY(SwingConstants.BOTTOM);
        frame.add(titleScreenBackground);
        frame.add(titlePanel);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(630, 300); //sets appropriate size for frame
        frame.setVisible(true); //makes frame visible
    }

I tried to make the panel a gridbaglayout so I could place the components in the same cell, but it still places the image first and then the button directly next to it.

EDIT: I have redone the code, making it do somewhat what I wanted. As you can see, the line where I try to set the location of the button does not do anything to the button.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • Possible [duplicate](http://stackoverflow.com/q/10861852/230513). – trashgod Jun 18 '14 at 00:27
  • Ok, I have managed to place the button on the image, but now I cannot align it. I am using the .setAlignmentY on the button but it still stays on the top in the middle. – user3741402 Jun 18 '14 at 00:49
  • @user3741402, Use an appropriate layout manager, BorderLayout is probably the easiest and update your code so we can see the changes. – camickr Jun 18 '14 at 00:52
  • See my answer. You changed the whole structure of the original code. There is no problem with using a JLabel. All you need to do is set the layout manager. Actually I take back my above comment. The easiest layout manager to use (to center a component) is a GridBagLayout and then just use the default GridBagConstraints when you add the button to the label. – camickr Jun 18 '14 at 01:14
  • `As you can see, the line where I try to set the location of the button does not do anything to the button.` - the default layout of a JPanel is a FlowLayout which will ignore your location. – camickr Jun 18 '14 at 01:18
  • I changed the code based on your advice, yet now the button disappears. – user3741402 Jun 18 '14 at 01:21
  • 2
    Another option would be to use a mouse listener. – Tim.DeVries Jun 18 '14 at 01:23
  • I will add that later, but the I can't use a listener if the button does not even appear :/ – user3741402 Jun 18 '14 at 01:27
  • 1
    No, you should not use a MouseListener on a JButton. You add an ActionListener to the button. – camickr Jun 18 '14 at 01:29
  • Right, that's what I meant, sorry about that. Regarding the missing button, do you have any advice on how to fix it? – user3741402 Jun 18 '14 at 01:30
  • @user3741402: Some more examples as cited [here](http://stackoverflow.com/a/11428289/1057230) and [here](http://stackoverflow.com/a/11372350/1057230) :-) – nIcE cOw Jun 18 '14 at 05:12

2 Answers2

4

how I would go about placing a button on top of an image in a GUI.

If you want to place a Swing button on top of an image then you need to follow 2 steps.

  1. set a layout manager for the label containing the image.

  2. add the button to the label (not the panel).

See Background Panel for more information and examples.

Edit:

To center a component the easiest approach is:

label.setLayout( new GridBagLayout() );
label.add(button, new GridBagConstraints());
camickr
  • 321,443
  • 19
  • 166
  • 288
  • Your original code added an icon to a JLabel. Why did you change that code? Why are you doing custom painting on a panel? – camickr Jun 18 '14 at 01:26
  • Is this comment for me? – user3741402 Jun 18 '14 at 01:28
  • @user3741402, yes, because you seem to be overlooking my original suggestion to the original code you posted. You are making this way to complicated. All you do is add the button to the label (which contains an Icon) and add the label to the frame. The key is that the label needs a layout manager in order for the component to appear, just like a JPanel needs a layout manager in order for the component to appear. – camickr Jun 18 '14 at 01:31
  • So you suggest adding an image onto a label, and place the button and the image label in a panel? – user3741402 Jun 18 '14 at 01:32
  • Yes, that is what my two steps suggested. I was in the middle of updating my previous comment with this advice again. – camickr Jun 18 '14 at 01:34
  • Ahh ok, I'll give this a go. Do I need to add a layout manager to both the label and the panel? – user3741402 Jun 18 '14 at 01:35
  • I reworked the code, yet the button still does not appear, even after I added a layout manager to both the background picture label and the button label. – user3741402 Jun 18 '14 at 01:46
  • The code you posted doesn't even compile. There is no class, no import statements and variables aren't defined. Again, why do you have all those components. I suggested you add the label to the frame and add the button to the label. All you need is three components, the frame, the label and the button. You don't need to set the layout manager of the frame, just the label. The point of a `SSCCE` is to keep the code simple to understand the basic concept. – camickr Jun 18 '14 at 01:54
  • Ok, I have added the button, it works perfectly fine now. At this point, how would I add the picture? Should I set the icon of a new label to the picture and then add the label to the frame or can I do it differently? – user3741402 Jun 18 '14 at 02:03
  • `Should I set the icon of a new label` - why are you talking about a new label? I said you only need 3 components. You just set the Icon of the label. Again, where is your updated SSCCE? – camickr Jun 18 '14 at 02:07
  • Ok, I have added the new code. I have added the variables and everything, yet the imports I can't place, they just get place as normal text. – user3741402 Jun 18 '14 at 02:12
  • I give up. You are NOT listening to what I have been saying. All you need is ONE label with an Icon. You set the layout for THAT label. You then add the button to THAT label. You then add THAT label to the frame. That is a total of THREE components, 1 frame, 1, label and 1 button. Why do you have a second label and a JPanel. Nowhere in my comments have I suggested you need a panel or a second label. This is my last comment. Good luck! – camickr Jun 18 '14 at 02:25
  • Ohhhhhhhhhhhhhh..... I get it... the picture is set as the label icon, and the button gets placed on top. That makes so much more sense, thank you very much! – user3741402 Jun 18 '14 at 02:31
  • Thank you so much, it works just how I wanted it to. Now to resize the button.... – user3741402 Jun 18 '14 at 02:38
  • `it works just how I wanted it to` - apparently not since the answer still hasn't been accepted after all the time I spent. – camickr Jun 18 '14 at 15:09
  • Sorry about that, I'm new on this website, I forgot about that. – user3741402 Jun 18 '14 at 23:49
-1

If you want button on the image you can just use image in paint method of JPanel. Example (with resource im

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestFrame extends JFrame {

BackgroundPane bgPane;

private JButton startButton;

public TestFrame() {
    super();
    initComponents();
}

private void initComponents() {

    try {

        URL url = getClass().getResource("battleship-650x0.jpg");
        BufferedImage image = ImageIO.read(url);

        bgPane = new BackgroundPane(image);
        bgPane.setLayout(new GridBagLayout());
        startButton = new JButton("Start");
        bgPane.add(startButton);
        setContentPane(bgPane);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        pack();

    } catch (Exception e) {
        e.printStackTrace();
    }

}

/**
 * @param args
 */
public static void main(String[] args) {
    TestFrame frame = new TestFrame();
    frame.setVisible(true);
}

class BackgroundPane extends JPanel {
    Image image;

    public BackgroundPane(Image backGroundImage) {
        super();
        image = backGroundImage;
        setPreferredSize(new Dimension(image.getWidth(this), image.getHeight(this)));
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
    }

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

    }

}
} 
A Stranger
  • 551
  • 2
  • 11
  • -1, There is no need to override the paint() method. You should NOT use the setPreferredSize() method. Instead you override the `getPreferredSize()` method. This was already suggested 5 hours earlier in the link to the `BackgroundPanel` which explains how painting is done. – camickr Jun 18 '14 at 15:08
  • `getPreferredSize()` and `setPreferredSize()` size are getter ans setter methods of a `Dimension` object. So I think overriding `getPreferredSize()` and using `setPreferredSize()` are effectively same – A Stranger Jun 20 '14 at 05:37