0

I cant seem to set a custom position of a button to JPanel. It always adds the button at the top left, and continues right. I also have a background image in place, which makes matters a bit more difficult. The Frame looks like this: imageshack.com/a/img838/3240/ez6l.png My code is:

private JFrame mainframe =  new JFrame();

public void main()
    {
    mainframe.setLocation(400, 150);
    mainframe.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    mainframe.setVisible(true);
    mainframe.setSize(800, 600);
    JPanel menupanel2 = new JPanel();
    JPanel MusicPanel = new JPanel();
    mainframe.setResizable(false);
    mainframe.setContentPane(new JLabel(new ImageIcon("src/res/LED0.png")));
    mainframe.setLayout(new FlowLayout());
    menupanel2.setBackground(Color.black);
    JButton PlayButton = new JButton("Play");
    PlayButton.setBackground(Color.green);
    JButton highscores = new JButton("Highscores");
    highscores.setBackground(Color.MAGENTA);
    JButton CustomButton = new JButton("Custom Shapes");
    CustomButton.setBackground(Color.orange);
    JButton HelpButton = new JButton("Help");
    HelpButton.setBackground(Color.red);
    JButton AboutButton = new JButton("About");
    AboutButton.setBackground(Color.yellow);
    final JButton MusicButton = new JButton("music");
    MusicButton.setPreferredSize(new Dimension(50, 50));
    CustomButton.setPreferredSize(new Dimension(140, 40));
    PlayButton.setPreferredSize(new Dimension(140, 40));
    HelpButton.setPreferredSize(new Dimension(140, 40));
    AboutButton.setPreferredSize(new Dimension(140, 40));
    highscores.setPreferredSize(new Dimension(140, 40));
    mainframe.add(menupanel2, BorderLayout.NORTH);
    mainframe.add(MusicPanel, BorderLayout.SOUTH);
    menupanel2.add(PlayButton, BorderLayout.NORTH);
    menupanel2.add(CustomButton, BorderLayout.NORTH);
    menupanel2.add(HelpButton, BorderLayout.NORTH);
    menupanel2.add(highscores, BorderLayout.NORTH);
    menupanel2.add(AboutButton, BorderLayout.NORTH);
    MusicPanel.add(MusicButton, BorderLayout.SOUTH);

I want to add the button "MusicButton " to the bottom right corner / middle/ or left. If there is a customized way in which you can order JButtons in JPanel, please share. Thanks

Dylan
  • 19
  • 1
  • 5
  • 1) See [Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?](http://stackoverflow.com/q/7229226/418556) (Yes.) 2) Please learn common [Java naming conventions](http://java.sun.com/docs/books/jls/second_edition/html/names.doc.html#73307) (specifically the case used for the names) for class, method & attribute names & use them consistently. – Andrew Thompson May 26 '14 at 00:54
  • *"How to place JButton in custom location in JPanel, while having background image in JFrame?"* Do it the same way you might do it when adding the button to a panel with no image BG. Add an `EmptyBorder`.. – Andrew Thompson May 26 '14 at 00:56
  • `menupanel2.add(PlayButton, BorderLayout.NORTH); menupanel2.add(CustomButton, BorderLayout.NORTH)` Only one component can be added to each constraint of a `BorderLayout`. – Andrew Thompson May 26 '14 at 00:58
  • @Andrew Thompson thanks for the tips. can you please edit my code as an answer? i would appreciate if you can get this to work and add extra corrections. Thanks Andrew – Dylan May 26 '14 at 01:01
  • 1
    *"can you please edit my code as an answer?"* I don't understand the question. 1) Provide ASCII art (or an image with a simple drawing) of the GUI as it should appear in smallest size and (if resizable) with extra width/height. 2) One way to get image(s) for an example is to hot-link to the images seen in [this answer](http://stackoverflow.com/a/19209651/418556). – Andrew Thompson May 26 '14 at 01:06
  • My Mainframe looks like this: http://imageshack.com/a/img838/3240/ez6l.png I want to edit it so that the button at the very right is at the bottom right. I want to do that with custom locations instead of simple code such as south. Regards – Dylan May 26 '14 at 01:12
  • *" I want to do that with custom locations instead of simple code such as south."* So, by 'custom locations' DYM 'magic'? If not, there is some logic to it that can be specified using layout managers and borders. Also note that doesn't tell me whether this GUI can be resized. – Andrew Thompson May 26 '14 at 01:16
  • It is set to resize as false. My example contains "mainframe.setResizable(false);" Also, what kind of examples in this situation? – Dylan May 26 '14 at 01:19
  • For better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete and Verifiable Example). If the image is really relevant to the problem (I doubt it is) it must be generated in code or hot-linked from the page mentioned earlier. BTW - **given the 'multiple GUI items' are all representing instances of one type of object, that suggests either a `JList` or a `JTable` would be best to display/edit them.** – Andrew Thompson May 26 '14 at 01:56
  • added the image as extra. But need all that code to show that if i have all these buttons in the JPanel, it just orders them from left to right at the top of the panel. Hope i can get an answer soon. I was looking for a solution to this, but all I found was people having custom button location in JFrame, not the panel. – Dylan May 26 '14 at 02:12
  • *"But need all that code.."* It is not what is included that is the 'not an MCVE', but what is not included. It needs imports, a `main(String[])` to put it on-screen.. It has to be a self contained *example* of the problem, as opposed to uncompilable code snippets. – Andrew Thompson May 26 '14 at 02:28

3 Answers3

2

Don't start throwing tomatoes if I'm wrong, but....

your mainframe layout is the FlowLayout

mainframe.setLayout(new FlowLayout());

You're specifying that your MusicPanel be set to a BorderLayout position on a JFrame that is set for the FlowLayout.

mainframe.add(MusicPanel, BorderLayout.SOUTH);

By doing this, you can't really predict what your GUI is going to look like when it compiles.This could be the source of your issue.

Also, on a side note, the compass references are no longer the preferred method of setting locations in a BorderLayout. http://docs.oracle.com/javase/tutorial/uiswing/layout/border.html


I would try setting your JFrame's layout to BorderLayout, set your MusicPanel to the PAGE_END (SOUTH) position of the JFrame. Then, use the GridBag layout on your MusicPanel and position your JButton to the LAST_LINE_END position.

Let me know how that works out!

Joshua Schlichting
  • 3,110
  • 6
  • 28
  • 54
2

I think you should do some research on layout in java. It's a good habit to make the frame.setVisible(true); at the last of your code. Here is my solution, Hope it can help you.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;



public class LayoutDemo {
    public static void main(String[] args) {
        LayoutDemo gridLayoutDemo = new LayoutDemo();
        try {
            gridLayoutDemo.createUI();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("File read exception");
            e.printStackTrace();
        }
    }

    public void createUI() throws IOException{
        JFrame frame = new JFrame("Grid Layout");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        JPanel mainPanel = new MainPanel("background.png");

        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
        frame.add(mainPanel,BorderLayout.CENTER);
        JPanel topPanel = new JPanel();
        topPanel.setOpaque(false);
        mainPanel.add(topPanel);        
        mainPanel.add(Box.createVerticalStrut(500));        
        BottomPanel bottomPanel = new BottomPanel();
        mainPanel.add(bottomPanel); 

        frame.setSize(820, 620);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    @SuppressWarnings("serial")
    class MainPanel extends JPanel{
        private Image background;

        public MainPanel(String fileName) throws IOException{
            background = ImageIO.read(new File(fileName));
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(background, 0, 0, this);
        }
    }

    @SuppressWarnings("serial")
    class BottomPanel extends JPanel{
        public BottomPanel(){
            LeftPanel leftPanel = new LeftPanel();
            leftPanel.setOpaque(false);
            leftPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
            RightPanel rightPanel = new RightPanel();
            rightPanel.setBorder(new EmptyBorder(0, 0 , 0, 0));
            rightPanel.setOpaque(false);
            add(leftPanel,BorderLayout.WEST);
            add(rightPanel,BorderLayout.EAST);

            setOpaque(false);
        }
    }

    @SuppressWarnings("serial")
    class LeftPanel extends JPanel{
        public LeftPanel(){
            setLayout(new GridLayout(1,5,5,10));
            setBorder(new EmptyBorder(0, 5, 0, 55));
            setOpaque(false);
            JButton playButton = new JButton("Play");
            playButton.setBackground(Color.green);
            playButton.setPreferredSize(new Dimension(140, 40));
            add(playButton);

            JButton shapesButton = new JButton("Custom Shapes");
            shapesButton.setBackground(Color.orange);
            add(shapesButton);

            JButton helpButton = new JButton("Help");
            helpButton.setBackground(Color.red);
            add(helpButton);

            JButton scoresButton = new JButton("HighScores");
            scoresButton.setBackground(new Color(120,81,169));
            add(scoresButton);

            JButton aboutButton = new JButton("About");
            aboutButton.setBackground(Color.yellow);
            add(aboutButton);
        }

    }

    @SuppressWarnings("serial")
    class RightPanel extends JPanel{
        public RightPanel(){
            setBorder(new EmptyBorder(0, 0, 0, 0));
            JButton button = new JButton(new ImageIcon("buttonIcon.png"));
            button.setBorder(new EmptyBorder(0, 0, 0, 0));;
            add(button,BorderLayout.CENTER);
        }
    }
}

Here is the operation effect. enter image description here

Eugene
  • 10,627
  • 5
  • 49
  • 67
2

enter image description here

This MCVE uses standard JSE layouts, insets and borders to create the GUI seen above. The trick to the white space in the GUI is commented in the source code as // 1 which can be explained by the simple (but longer) instruction // Adjust numbers as required.

Drag it wider and taller to see that:

  • The extra width of the UI is divided up between each button roughly equally. The 'black' button sticks to the RHS of the UI.
  • The extra height is shown between the top row of buttons and the bottom button.

import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class ShapeShape {

    // the GUI as seen by the user (without frame)
    JPanel ui = new JPanel(new BorderLayout());

    public static final String[] ACTIONS = {
        "Play", "Custom Shapes", "Help", "High Scores", "About"
    };

    public static final Color[] COLORS = {
        Color.GREEN,Color.ORANGE,Color.RED,Color.MAGENTA,Color.YELLOW
    };

    ShapeShape() {
        initUI();
    }

    public void initUI() {
        ui.setBorder(new EmptyBorder(20, 30, 20, 30)); // 1

        JPanel menuPanel = new JPanel(new GridLayout(1, 0, 10, 10)); // 1
        ui.add(menuPanel, BorderLayout.PAGE_START); 
        Insets insets = new Insets(10, 20, 10, 20); // 1
        for (int ii=0; ii<ACTIONS.length; ii++) {
            JButton b = new JButton(ACTIONS[ii]);
            b.setMargin(insets);
            Font f = b.getFont();
            b.setFont(f.deriveFont(f.getSize()*1.4f)); // 1
            b.setBackground(COLORS[ii]);
            menuPanel.add(b);
        }

        Image img = new BufferedImage(60,60, BufferedImage.TYPE_INT_RGB);
        JPanel exitPanel = new JPanel(new FlowLayout(SwingConstants.RIGHT));
        exitPanel.setBorder(new EmptyBorder(15, 0, 0, 15)); // 1
        JButton b = new JButton(new ImageIcon(img));
        exitPanel.add(b);
        ui.add(exitPanel, BorderLayout.PAGE_END);
    }

    public final JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {

                ShapeShape o = new ShapeShape();

                JFrame f = new JFrame("Demo");
                f.add(o.getUI());
                // Ensures JVM closes after frame(s) closed and
                // all non-daemon threads are finished
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                // See http://stackoverflow.com/a/7143398/418556 for demo.
                f.setLocationByPlatform(true);

                // ensures the frame is the minimum size it needs to be
                // in order display the components within it
                f.pack();
                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                f.setVisible(true);
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433