2

Desired main GUI

Basically, how do I generate this? I'm pretty sure this is a job for GridBagLayout, but I'm unable to wrap my head around how to properly size the 'Action Pane' versus the 'Menubar'. The red & black lines indicate the grid that I believe you are to use in this case (3x3), but I might be completely wrong and there could be a way to do it in a different configuration. I tried to mess around with the weightx, weighty, gridheight, gridwidth values in GridBagConstraints, but I can't achieve my goals here.

Note that the second red line is supposed to be exactly one-third of the height of the bottom half of the frame.

This is my latest attempt, by trying to use a 3x6 grid (c is the GridBagConstraints object, characterPortraits contain all the portraits, and currentScreen is the 'Action Pane') :

c.fill = GridBagConstraints.BOTH;
    c.weightx = 0.25;
    c.weighty = (1/6);
    c.gridx = 0;
    c.gridy = 0;
    c.gridheight = 3;
    pane.add(characterPortraits.get(0), c);  

    c.gridx = 2;        
    pane.add(characterPortraits.get(1), c);          

    c.gridx = 0;
    c.gridy = 3;
    c.gridheight = 3;
    pane.add(characterPortraits.get(2), c);  

    c.gridx = 2;        
    pane.add(characterPortraits.get(3), c);

    //c.fill = GridBagConstraints.NONE;
    c.weightx = 1.0;
    c.weighty = 1.0;
    c.gridx = 1;
    c.gridy = 0;
    c.gridheight = 3;
    pane.add(currentScreen, c);    

Instead, this produces each portrait in the bottom third of its quadrant, and the Action Pane taking 5/6 of the center column instead of 4/6, like I want it to. Any ideas would help; thanks! -B.

EDIT: I'm designing this application to have a fixed window size; people may say this is bad design, but I'm really just trying to get a feel for Swing components and make sure they at least behave in a fixed window the way I want them to. I think I may allow for a maximize proper-resizing, but that's about it.

Billy M.
  • 369
  • 2
  • 16
  • If the window stretches, what components do you want to take the available space (horizontal and vertical)? – arcy Jun 22 '12 at 23:26
  • all of elements are resiziable ??? – mKorbel Jun 22 '12 at 23:30
  • Thanks for the questions; addressed them in the edit I just made. – Billy M. Jun 22 '12 at 23:31
  • 1
    Have you tried using a 3x3 grid, set all weights to 1, set sizes for the ActionPane and MenuBar, let the ActionPane, Portrait2, and Portrait4 span two cells vertically? If you're targeting a window of a fixed size, setting the sizes of two components (or even 6) bother you... – arcy Jun 22 '12 at 23:45
  • 1
    Look at miglayout. It's easier to use for this than gridbaglayout. – Hovercraft Full Of Eels Jun 22 '12 at 23:49
  • *"may allow for a maximize proper-resizing, but that's about it."* If you can get it to work for 2 sizes, it should work for anything in between. – Andrew Thompson Jun 23 '12 at 06:19
  • BTW - if the 'red lines' indicate 1/3, does that mean that portraits 2 & 4 are twice the height of portraits 1 & 3? While I admire your effort at posting a mock-up, I can't say I understand it. – Andrew Thompson Jun 23 '12 at 06:23

2 Answers2

5

Though, it appeared strange to me that you adding your JMenuBar, at the most weird of positions. Though what you can do, to overcome the difficulty mentioned by you in this line

Instead, this produces each portrait in the bottom third of its quadrant, and the 
Action Pane taking 5/6 of the center column instead of 4/6, like I want it to.

is to add one JPanel at this location and put your ActionPane and JmenuBar to this added JPanel, to achieve the desired outcome. So I had added centerPanel at this location to demonstrate, how this can be achieved.

I hope this output is what you so desired :

OUTPUT

And here is the code responsible for this output :

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

public class GridBagPanelLayout
{
    private JPanel portrait1;
    private JPanel portrait2;
    private JPanel portrait3;
    private JPanel portrait4;
    private JPanel centerPanel;

    private JPanel actionPane;

    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("GridBag JPanel Layout Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        /*
         * This JPanel will serve as the 
         * Content Pane, for the JFrame.
         */
        JPanel contentPane = new JPanel();
        contentPane.setOpaque(true);
        contentPane.setBackground(Color.WHITE);
        contentPane.setLayout(new GridBagLayout());

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.FIRST_LINE_START;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 0.33;
        gbc.weighty = 0.5;
        gbc.gridheight = 2;

        portrait1 = new JPanel();
        portrait1.setOpaque(true);
        portrait1.setBackground(Color.BLUE);
        portrait1.setBorder(
                    BorderFactory.createMatteBorder(
                            2, 2, 2, 2, Color.WHITE));
        contentPane.add(portrait1, gbc);

        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.weighty = 1.0;
        gbc.gridheight = 4;

        centerPanel = new JPanel();
        centerPanel.setOpaque(true);
        centerPanel.setBackground(Color.WHITE);
        centerPanel.setLayout(new GridBagLayout());
        GridBagConstraints constCenter = new GridBagConstraints();
        constCenter.anchor = GridBagConstraints.FIRST_LINE_START;
        constCenter.fill = GridBagConstraints.BOTH;
        constCenter.gridx = 0;
        constCenter.gridy = 0;
        constCenter.weightx = 1.0;
        constCenter.weighty = 0.975;

        actionPane = new JPanel();
        actionPane.setOpaque(true);
        actionPane.setBackground(Color.MAGENTA);
        actionPane.setBorder(
                    BorderFactory.createMatteBorder(
                            2, 2, 2, 2, Color.WHITE));
        centerPanel.add(actionPane, constCenter);

        constCenter.gridx = 0;
        constCenter.gridy = 1;
        constCenter.weighty = 0.025;

        centerPanel.add(getMenuBar(), constCenter); 
        contentPane.add(centerPanel, gbc);  

        gbc.gridx = 2;
        gbc.gridy = 0;
        gbc.weighty = 0.5;
        gbc.gridheight = 2;

        portrait3 = new JPanel();
        portrait3.setOpaque(true);
        portrait3.setBackground(Color.BLUE);
        portrait3.setBorder(
                    BorderFactory.createMatteBorder(
                            2, 2, 2, 2, Color.WHITE));
        contentPane.add(portrait3, gbc);

        gbc.gridx = 0;
        gbc.gridy = 2;
        //gbc.weighty = 0.5;
        //gbc.gridheight = 2;

        portrait2 = new JPanel();
        portrait2.setOpaque(true);
        portrait2.setBackground(Color.BLUE);
        portrait2.setBorder(
                    BorderFactory.createMatteBorder(
                            2, 2, 2, 2, Color.WHITE));
        contentPane.add(portrait2, gbc);

        gbc.gridx = 2;
        gbc.gridy = 2;
        gbc.weighty = 0.5;
        gbc.gridheight = 2;

        portrait4 = new JPanel();
        portrait4.setOpaque(true);
        portrait4.setBackground(Color.BLUE);
        portrait4.setBorder(
                    BorderFactory.createMatteBorder(
                            2, 2, 2, 2, Color.WHITE));
        contentPane.add(portrait4, gbc);

        frame.setContentPane(contentPane);
        frame.setSize(500, 300);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JMenuBar getMenuBar()
    {
        JMenuBar menuBar = new JMenuBar();

        JMenu fileMenu = new JMenu("File");
        fileMenu.setOpaque(true);
        fileMenu.setBackground(Color.BLACK);
        fileMenu.setForeground(Color.WHITE);
        JMenuItem newItem = new JMenuItem("NEW");
        JMenuItem openItem = new JMenuItem("OPEN");
        fileMenu.add(newItem);
        fileMenu.add(openItem);

        JMenu editMenu = new JMenu("Edit");
        editMenu.setOpaque(true);
        editMenu.setBackground(Color.BLACK);
        editMenu.setForeground(Color.WHITE);
        JMenuItem redoItem = new JMenuItem("Redo");
        JMenuItem undoItem = new JMenuItem("Undo");
        editMenu.add(redoItem);
        editMenu.add(undoItem);

        JMenu viewMenu = new JMenu("View");
        viewMenu.setOpaque(true);
        viewMenu.setBackground(Color.BLACK);
        viewMenu.setForeground(Color.WHITE);
        JMenuItem zInItem = new JMenuItem("Zoom In");
        JMenuItem zOutItem = new JMenuItem("Zoom Out");
        viewMenu.add(zInItem);
        viewMenu.add(zOutItem);

        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        menuBar.add(viewMenu);
        menuBar.setOpaque(true);
        menuBar.setBackground(Color.BLACK);     

        return menuBar;
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new GridBagPanelLayout().createAndDisplayGUI();
            }
        });
    }
}
nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
  • @nIcE cOw : Thanks for the commentary and code! That's pretty close to what I want, except for the fact that my "menubar" is not meant to be a `JMenuBar`, this is probably my mistake for being unclear with calling it my "menubar". It is really just a fancy menu-LIKE bar with similar options, but with custom colours and a mouse-over custom picture attached along with it. Thanks again! – Billy M. Jun 26 '12 at 22:51
  • Curious... if I specify the `weightx` in the beginning as 0.33 then it works how you displayed it, but if I specify it more exactly as (1 / 3), then the portraits appear smooshed into the center and very small - why is this? – Billy M. Jun 28 '12 at 21:41
  • 1
    Sorry for the late reply, that was `NIGHT` time when you send that message. I guess the answer is in the basics of the Java Language, the result of division of two `Integer` values is also an `Integer`, so the value goes to the `result variable` after `Casting` which is zero, that's why. Try something like `1.0/3.0`, I guess that is the difference :-) Hence the `MORAL` exact way is `0.333` and not `1/3` :-) – nIcE cOw Jun 29 '12 at 04:06
  • Or you can write `(double) 1 / 3` – nIcE cOw Jun 29 '12 at 04:12
  • 1
    funny... I was writing `(double) (1 / 3)` before, but I guess the order-of-operations still made it cast to an integer instead. Thanks again very much. – Billy M. Jun 29 '12 at 16:37
  • @BillyM. : Please do watch closely as to what I wrote ((double) 1 / 3), here first 1 will be cast to double than division by 3 is done. **Though in your case you wrote ((double) (1 / 3)), here first brackets are solved thus 1 divided by 3 will again give zero, and than the result will be cast to double. So answer will be something like 0.000 in your case** To watch the brackets in both the cases :-) – nIcE cOw Sep 22 '12 at 16:41
4

I've never been a big fan of GridBagLayout. It's hard to get right - each component can have up to 11 constraints - it's hard to maintain, and reusing the same constraints object can lead to unintended consequences.

Instead, I prefer to nest various types of layout. To me, you clearly have:

  1. A BorderLayout, with West, Center, and East panels
  2. Inside the West panel, you have a GridLayout - 2 rows, 1 column (Portraits 1 and 2).
  3. Inside the East panel, you have a GridLayout - 2 rows, 1 column (Portraits 3 and 4).
  4. Inside the Center panel, you have another BorderLayout, with a Center component (Action Pane) and a South component (Menubar).

The only limitation to this is that the West panel and East panel are not logically connected. If Portraits 1, 2, 3, and 4 are all of the same size, that's not a problem. If they're of different sizes, you may find that the West and East panels will be shaped differently.

David Koelle
  • 20,726
  • 23
  • 93
  • 130
  • +1 for `Nested Layout`. If you want them to be of almost same size, you can first put a `JPanel` on `WEST/EAST/LINE_START/LINE_END` and then add `portrait JPanel` on top of that, that can lead to them having almost equal sizes. Please have a look at this example shown [here](http://stackoverflow.com/questions/3420311/java-swing-button-colors/3420431#3420431) by @trashgod and another one [here](http://stackoverflow.com/questions/10369982/jbuttons-inside-jpanels-with-a-gridlayout-jframe/10372005#10372005). – nIcE cOw Jun 23 '12 at 04:49
  • No doubt, `GridBagLayout` is not easy to handle, though the outcome that one gets at the end is always pleasing. – nIcE cOw Jun 23 '12 at 04:49
  • I want to accept both of your answers, but I prefer nIcE cOw's above this because of the greater control and flexibility than `GridLayout` and `BorderLayout` provide. Very good stuff here, though - thanks again. – Billy M. Jun 27 '12 at 02:56