简体   繁体   中英

What settings should I use to resolve this GridBagLayout resizing issue?

I have been searching and trying ways to resolve the problems I encountered with GridBagLayout resizing but to no avail. The problems are:

  1. I drag the bottom of the JDialog window down to make it taller; the search panel (above panel in the below screenshot) kept getting taller, just adding white space that it didn't need for its contents (I don't want this wasted space which takes height away from the scrolling table below it).

  2. If I move the right side of the window to make it a bit narrower, the scroll panel becomes too short even though my screen and the window could have displayed its full height; a vertical scroll bar appears (I don't like the panels to scroll vertically, just horizontally.)

My JDialog that holds below components in the upper right portion uses below layout manager and constraints:

JPanel      level 1         uses GridBagLayout Setting 1 (see below)
JScrollPane level 2         uses GridBagLayout Setting 1  
JPanel      level 3         uses GridBagLayout Setting 2
JPanel      level 4         uses GridBagLayout Setting 2
JPanel      level 5         uses GridBagLayout Setting 2
JPanel      level 5         uses GridBagLayout Setting 2

GridBagLayout.GridBagConstraints (c)

Setting 1:

c.fill = GridBagConstraints.BOTH;
c.weightx = 99.0;
c.weighty = 99.0;

Setting 2:

c.fill = GridBagConstraints.NONE;
c.weightx = 1.0;
c.weighty = 1.0;

Originally, this is my JDialog if I don't use JScrollPane :

在此输入图像描述

If I drag the window to make it bigger, the size of the JPanel (which was what I use before I used JScrollPane to make it scrollable horizontally) remains as it is. I want to achieve the same behavior, only that I want to make it horizontally scrollable.

What layout manager should I use to resolve this resizing problem? If I have to really use GridBagLayout , what constraints/settings should I use? I would highly appreciate any suggestion. Thank you!

UPDATE 1 ------------------------------------------------------

Kindly check sample code scenario below. Both scrollable panels (RED and BLUE) use GridBagConstraints.BOTH , weightx and weighty equal to 99.0 . I want the red panel to have a height that is enough to contain the text field. I also want that when the dialog is dragged down to make the window bigger, the red panel's height remains the same. Please note that in the actual screen, both panels' number of contents may change (add/minus buttons exist), hence, setting of minimum panel size (for resizing) won't help. Kindly advise how I should go about this case. Thanks!

package cfr.view.search;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

public class GBLSample extends JDialog {

    private JPanel contentPane;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    GBLSample frame = new GBLSample();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public GBLSample() {
        setBounds(100, 100, 350, 400);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        GridBagLayout gbl_contentPane = new GridBagLayout();
        contentPane.setLayout(gbl_contentPane);

        // RED PANEL ------------------------------------------------ 
        JScrollPane sp1 = new JScrollPane();
        GridBagConstraints gbc1 = new GridBagConstraints();
        gbc1.fill = GridBagConstraints.BOTH;
        gbc1.weightx = 99.0;
        gbc1.weighty = 99.0;
        contentPane.add(sp1, gbc1);

        JPanel redPanel = new JPanel();
        redPanel.setBackground(Color.RED);
        JTextField field = new JTextField(20);
        GridBagConstraints gbc2 = new GridBagConstraints();
        gbc2.anchor = GridBagConstraints.PAGE_START;
        gbc2.fill = GridBagConstraints.NONE;
        contentPane.add(field, gbc2);

        redPanel.add(field);
        sp1.setViewportView(redPanel);

        // BLUE PANEL ------------------------------------------------ 
        JScrollPane sp2 = new JScrollPane();
        GridBagConstraints gbc3 = new GridBagConstraints();
        gbc3.fill = GridBagConstraints.BOTH;
        gbc3.gridx = 0;
        gbc3.gridy = 1;
        gbc3.weightx = 99.0;
        gbc3.weighty = 99.0;
        contentPane.add(sp2, gbc3);

        JPanel bluePanel = new JPanel();
        bluePanel.setBackground(Color.BLUE);
        sp2.setViewportView(bluePanel);
    }
}

UPDATE 2 ------------------------------------------------------

Still have the same problem with the JPanel's sizing as #1 above. Problem 1

在此输入图像描述

try this code:

package test;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;

public class GridBagLayoutSample extends JFrame {

private JPanel contentPane;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                GridBagLayoutSample frame = new GridBagLayoutSample();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */
public GridBagLayoutSample() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    GridBagLayout gbl_contentPane = new GridBagLayout();
    gbl_contentPane.columnWidths = new int[]{0, 0};
    gbl_contentPane.rowHeights = new int[]{50, 0, 0};
    //the 1.0 value in columnWeights let redPanel and scrollPane (that contain bleuPanel) grow horizontally
    //the 1.0 value is in the first index so it affect the first column
    //you still need to use a valid value for gbc_redPanel.fill and gbc_scrollPane.fill;
    gbl_contentPane.columnWeights = new double[]{1.0, Double.MIN_VALUE};
    //the 0.0 value of rowWeights => components in first row will not grow
    //the 0.0 value of rowWeights => components in second row will grow
    gbl_contentPane.rowWeights = new double[]{0.0, 1.0, Double.MIN_VALUE};
    contentPane.setLayout(gbl_contentPane);

    JPanel redPanel = new JPanel();
    redPanel.setBackground(Color.RED);
    GridBagConstraints gbc_redPanel = new GridBagConstraints();
    gbc_redPanel.insets = new Insets(0, 0, 5, 0);
    gbc_redPanel.fill = GridBagConstraints.BOTH;
    gbc_redPanel.gridx = 0;
    gbc_redPanel.gridy = 0;
    contentPane.add(redPanel, gbc_redPanel);

    JScrollPane scrollPane = new JScrollPane();
    GridBagConstraints gbc_scrollPane = new GridBagConstraints();
    gbc_scrollPane.fill = GridBagConstraints.BOTH;
    gbc_scrollPane.gridx = 0;
    gbc_scrollPane.gridy = 1;
    contentPane.add(scrollPane, gbc_scrollPane);

    JPanel bleuPanel = new JPanel();
    bleuPanel.setBackground(Color.BLUE);
    //scrollpane work with the preferred size of the component in the viewportView
    //try to change this values
    bleuPanel.setPreferredSize(new Dimension(400, 400));
    scrollPane.setViewportView(bleuPanel);
}

}

add this to your code

gbl_contentPane.rowHeights = new int[]{40, 0, 0};
gbl_contentPane.rowWeights = new double[]{0.0,0.0, 1.0, Double.MIN_VALUE};
gbc1.gridx = 0;
gbc1.gridy = 0;

and remove this

gbc1.weightx = 99.0;
gbc1.weighty = 99.0;

I have been searching and trying ways to resolve the problems I encountered with GridBagLayout resizing but to no avail.

Welcome to GridBagLayout .

First thing to note is that in

        JPanel redPanel = new JPanel();
        redPanel.setBackground(Color.RED);
        JTextField field = new JTextField(20);
//      GridBagConstraints gbc2 = new GridBagConstraints();
//      gbc2.anchor = GridBagConstraints.PAGE_START;
//      gbc2.fill = GridBagConstraints.NONE;
//      contentPane.add(field, gbc2);

        redPanel.add(field);
        sp1.setViewportView(redPanel);

You are adding the text field to the content pane and then adding it again to the panel, which overrides your previous assignment (a component can only belong to one container). I commented out the lines which do nothing. The choice for how to lay out the text field in the red panel is completely different than the choice of how to lay out the red panel in the content pane.

I want the red panel to have a height that is enough to contain the text field.

That is taken care of by the layout manager. However, if you resize the window manually so that the panel will not have enough space, then scrollbars will appear provided that the panel is in a JScrollPane . You can try to @Override the getMinimumSize of the panel to its getPreferredSize , but not all layout managers respect it, I believe.

Regardless, I don't see why you need the scroll pane for the red panel at all.

I also want that when the dialog is dragged down to make the window bigger, the red panel's height remains the same.

Then you should set its weighty to 0 .

Note: don't use underscores ( _ ) in non-final variable names in accordance with the Java naming conventions ( gbl_contentPane should be gblContentPane ).

Edit

Here is an example of of dynamically changing the allocated size for the redPanel . I use BorderLayout for the content pane (also suggested by Dan O) for simplicity.

public class GBLSample extends JDialog {

    private JPanel contentPane;
    private JScrollPane redSP = new JScrollPane(new RedPanel());

    public static void main(String[] args) {

        EventQueue.invokeLater(() -> {
            GBLSample frame = new GBLSample();
            frame.setVisible(true);
        });
    }

    private class RedPanel extends JPanel {

        RedPanel() {

            setLayout(new GridBagLayout());
            setBackground(Color.RED);

            GridBagConstraints c = new GridBagConstraints();
            c.anchor = GridBagConstraints.FIRST_LINE_START;
            add(new JTextField(10), c);
            c.weightx = 1;
            c.gridx = 1;
            add(new JComboBox<>(), c);
            c.weightx = 0;
            c.gridx = 0;
            add(new JComboBox<>(), c);
            c.gridx = 1;
            add(new JComboBox<>(), c);
            c.weighty = 1;
            c.gridx = 0;
            c.gridy = 2;
            add(new JButton("SSSS"), c);
        }

        @Override
        public Dimension getPreferredSize() {

            Dimension dim = super.getPreferredSize();
            JScrollBar sb = redSP.getHorizontalScrollBar();
            if (!sb.isShowing())
                return dim;
            return new Dimension(dim.width, dim.height + sb.getHeight());
        }
    }

    public GBLSample() {

        setBounds(100, 100, 350, 400);
        contentPane = new JPanel(new BorderLayout());
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);

        // RED PANEL ------------------------------------------------
        redSP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
        contentPane.add(redSP, BorderLayout.PAGE_START);

        // BLUE PANEL ------------------------------------------------
        JPanel bluePanel = new JPanel();
        bluePanel.setBackground(Color.BLUE);
        contentPane.add(new JScrollPane(bluePanel));
    }
}

The idea is to add all extra space at the bottom of the panel by giving all the weight to a component on the bottom (and similarly can be done for the x axis with a right-most component). When the scrollbar is shown, the panel recalculates its height and adds the scrollbar's height to to itself (to the bottom most component), then the scrollbar does not hide anything.

Maybe a GridBagLayout might not be suited for your current UI, and a BorderLayout would work better? Put the red panel in BorderLayout.NORTH and put the blue panel in BorderLayout.CENTER . Components in the CENTER region will grow and shrink as you resize your dialog, and your red panel's preferredSize will be respected as you +/- items.

Unfortunately, there was a bug in the system's overridden JPanel.getMinimumSize() that was causing my search panel to get squished out of existence. I was able to find a fix for it already without changing any setting with the system's customized layout manager. Still, thanks a lot for all your answers and help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM