InnerOrchestra
InnerOrchestra

Reputation: 47

Gridbag layout -> how to stop components from resizing along with the window?

I have a JFframe form in NetBeans 8 / Java 7.

It has a bunch of labels, textboxes, dropdowns, etc. These are a column on the left size, all staked up on top of each other.

Here's a screenshot:

enter image description here

How can I prevent all those components from sticking to the right and resizing along with the window and at the same time have the preview frame at the far right resize along?

I'm new to Java, and the gridbaglayout was the only I found to align everything properly. I just want the left side to have its components well aligned and not moving around. And I just want the right side, the panel, to resize according to the window resize.

Thank you,

Upvotes: 2

Views: 9586

Answers (3)

Jan Bodnar
Jan Bodnar

Reputation: 11647

the gridbaglayout was the only I found to align everything properly.

The MigLayout manager can do that easily. It also provides much better portability. Notice the usage of related gaps (r), dialog insets (dialog) and logical pixels (lp). These units are translated to pixels accordingly. On the other hand, GridbagLayout sets spaces directly in pixels which is inadequate, e.g. changing font or resolution will affect the layout.

See to following code example:

package com.zetcode;

import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;


public class MigLayoutPreview2 extends JFrame {

    public MigLayoutPreview2() {

        initUI();

        setTitle("Design preview");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    private void initUI() {

        JPanel pnl = new JPanel(new MigLayout("ins dialog, wrap"));

        pnl.add(new JLabel("Source PDF file..."), "pad 0 -5lp 0 0");
        pnl.add(new JButton("Browse"), "growx");
        pnl.add(new JLabel("Height (inches):"), "sgx, split 2");
        pnl.add(new JTextField(10), "growx");
        pnl.add(new JLabel("Width (inches):"), "sgx, split 2");
        pnl.add(new JTextField(10), "growx"); 
        pnl.add(new JButton("More PDF attributes"), "growx");
        pnl.add(new JSeparator(), "pad 0 -5lp 0 0, gaptop r, growx");
        pnl.add(new JLabel("Set bounding box..."), "pad 0 -5lp 0 0");
        pnl.add(new JComboBox(), "growx");
        pnl.add(new JSeparator(), "pad 0 -5lp 0 0, gaptop r, growx");
        pnl.add(new JLabel("Sheet size..."), "pad 0 -5lp 0 0");
        pnl.add(new JComboBox(), "growx");
        pnl.add(new JLabel("Height (inches):"), "sgx, split 2");
        pnl.add(new JTextField(10), "growx");
        pnl.add(new JLabel("Width (inches):"), "sgx, split 2");
        pnl.add(new JTextField(10), "growx"); 
        pnl.add(new JSeparator(), "pad 0 -5lp 0 0, gaptop r, growx");

        JPanel rpnl = new JPanel();
        rpnl.setBorder(BorderFactory.createEtchedBorder());

        pnl.add(rpnl, "cell 2 0, w 90, spany, pushx, grow");

        add(pnl);
        pack();
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MigLayoutPreview2 ex = new MigLayoutPreview2();
                ex.setVisible(true);
            }
        });
    }
}

I have reproduced part of your screenshot and have also kept the indents. Horizontal separators do not stretch completly, since I believe this is not optimal design. The design is also improved by eliminating the huge spaces between labels and text fields.

Design preview

Upvotes: 0

splungebob
splungebob

Reputation: 5415

You need to set the fill constraint to NONE.

Tutorial: How to Use GridBagLayout:

When you add each Component to the panel, it would look something like this (from the tutorial):

JPanel pane = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();

//For each component to be added to this container:
//...Create the component...
//...Set instance variables in the GridBagConstraints instance...
pane.add(theComponent, c);

you need to ensure that you call:

c.fill = GridBagConstraints.NONE;

for every constraints object for each Component that you add to the panel that you don't want to stretch horizontally.

If you're resusing the same constraints object for each component, you can simply set it once for all if that's you're desired result.

EDIT:

As some others have pointed out, the OP may want the fields to stretch, but only up to a certain limit (which is still not clear at this point). In that case, you would use a combination of

c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0;

as already pointed out. Example:

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

public class GridBagDemo implements Runnable
{
  public static void main(String[] args)
  {
    SwingUtilities.invokeLater(new GridBagDemo());
  }

  public void run()
  {
    // 4 components that all have different widths
    JButton btnBrowse = new JButton("Browse");
    JTextField txfHeight = new JTextField(4);
    JTextField txfWidth = new JTextField(10);
    JButton btnMore = new JButton("More PDF Attributes");

    // the preview pane?
    JTextArea txaPreview = new JTextArea(8, 20);
    JScrollPane scrPreview = new JScrollPane(txaPreview);
    scrPreview.setVerticalScrollBarPolicy(
        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

    GridBagConstraints gbc = new GridBagConstraints();
    // we'll use these constraints for all components
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.insets = new Insets(2,4,2,4);

    JPanel panel = new JPanel(new GridBagLayout());

    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.NONE;
    gbc.weightx = 0;
    panel.add(new JLabel("Source PDF size..."), gbc);

    gbc.gridx = 0;
    gbc.gridy = 1;
    gbc.gridwidth = 2;
    gbc.gridheight = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    panel.add(btnBrowse, gbc);

    gbc.gridx = 0;
    gbc.gridy = 2;
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.NONE;
    gbc.weightx = 0;
    panel.add(new JLabel("Height (in inches):"), gbc);

    gbc.gridx = 1;
    gbc.gridy = 2;
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    panel.add(txfHeight, gbc);

    gbc.gridx = 0;
    gbc.gridy = 3;
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.NONE;
    gbc.weightx = 0;
    panel.add(new JLabel("Width (in inches):"), gbc);

    gbc.gridx = 1;
    gbc.gridy = 3;
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    panel.add(txfWidth, gbc);

    gbc.gridx = 0;
    gbc.gridy = 4;
    gbc.gridwidth = 2;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    panel.add(btnMore, gbc);

    gbc.gridx = 0;
    gbc.gridy = 5;
    gbc.gridwidth = 2;
    gbc.fill = GridBagConstraints.VERTICAL;
    gbc.weighty = 1;
    panel.add(Box.createVerticalGlue(), gbc);

    gbc.gridx = 2;
    gbc.gridy = 0;
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.NONE;
    gbc.weightx = 0;
    gbc.weighty = 0;
    panel.add(new JLabel("Preview"), gbc);

    gbc.gridx = 2;
    gbc.gridy = 1;
    gbc.gridwidth = 1;
    gbc.gridheight = 8; // some number that's > the number of entry rows
    gbc.fill = GridBagConstraints.BOTH;
    gbc.weightx = 1;
    gbc.weighty = 1;
    panel.add(scrPreview, gbc);

    JFrame frame = new JFrame("GrigBag Demo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(new JScrollPane(panel), BorderLayout.CENTER);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}

Upvotes: 1

Braj
Braj

Reputation: 46841

I just want the right side, the panel, to resize according to the window resize.

By default all the columns are divided in equal percentage in each row.

To force the second (right side) column to take the more space, assign it a higher percentage using GridBagConstraints#weightx

gc.weightx = 0.75; // 75%

Don't forget to fill the horizontal space completely using GridBagConstraints#fill

gc.fill = GridBagConstraints.HORIZONTAL;

If you want fixed width for first column then set the preferred size for the left side panel by overriding getPreferredSize() method and assign 100% width to the right side panel.

JPanel leftSidePanel = new JPanel() {

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(..., ...);
    }
}

Have a look at my another post GridBagLayout: How to set fixed column width? that explain it better.

It;s worth reading Swing Tutorial on Solving Common Layout Problems

Upvotes: 1

Related Questions