How do I use GridBayLayout in Java (Swing) to gene

2019-01-09 18:33发布

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.

2条回答
狗以群分
2楼-- · 2019-01-09 19:08

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();
            }
        });
    }
}
查看更多
ら.Afraid
3楼-- · 2019-01-09 19:16

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.

查看更多
登录 后发表回答