How do I use GridBayLayout in Java (Swing) to generate this particular image in my frame?
Asked Answered
C

2

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.

Carollcarolle answered 22/6, 2012 at 23:16 Comment(7)
If the window stretches, what components do you want to take the available space (horizontal and vertical)?Phraseogram
all of elements are resiziable ???Anaanabaena
Thanks for the questions; addressed them in the edit I just made.Carollcarolle
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...Phraseogram
Look at miglayout. It's easier to use for this than gridbaglayout.Waterer
"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.Deprivation
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.Deprivation
A
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();
            }
        });
    }
}
Arp answered 23/6, 2012 at 4:39 Comment(6)
@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!Carollcarolle
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?Carollcarolle
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 :-)Arp
Or you can write (double) 1 / 3Arp
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.Carollcarolle
@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 :-)Arp
M
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.

Monadelphous answered 23/6, 2012 at 2:5 Comment(3)
+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 by @trashgod and another one here.Arp
No doubt, GridBagLayout is not easy to handle, though the outcome that one gets at the end is always pleasing.Arp
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.Carollcarolle

© 2022 - 2024 — McMap. All rights reserved.