Search code examples
javaswinglayoutlayout-managergridbaglayout

Swing using GridBagLayout with GridBagConstraints


First java GUI app that I'm making.

Basically, what I want to achieve looks pretty simple. It's a simple horizontal layout which contains a simple JLabel first, a JTextArea, JButton and at least another JLabel.

This is a simple pic I've made to illustrate: enter image description here

Just to clarify, I don't want the text area and the bottom label to have fixed sizes but to fill the space they have, and also to have some little padding between the other components.

This is the code I made so far, as you can see in the picture above, it isn't yet what I'm trying to achieve:

public class QueryPanel extends JPanel{
    private JLabel headerLabel;

    private String defaultString = "Insert query here...";
    private boolean isTextFieldClicked = false;
    private JTextArea queryTextArea;
    private JScrollPane queryScrollPane;

    private JButton executeQueryButton;

    private JTextArea resultTextArea;
    private JScrollPane resultScrollPane;

    public QueryPanel(String headerText){
        GridBagLayout gridLayout = new GridBagLayout();
        setLayout(gridLayout);

        GridBagConstraints constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.HORIZONTAL;
        headerLabel = new JLabel();
        headerLabel.setText(headerText);
        constraints.gridy = 0;
        add(headerLabel, constraints);

        queryTextArea = new JTextArea(defaultString);
        queryScrollPane = new JScrollPane(queryTextArea);
        constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.weighty = 1.0;
        constraints.weightx = 1.0;
        constraints.gridy = 1;
        add(queryScrollPane, constraints);

        executeQueryButton = new JButton("Execute Query");
        constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.gridy = 2;
        add(executeQueryButton, constraints);

        resultTextArea = new JTextArea();
        resultTextArea.setEditable(false);
        resultScrollPane = new JScrollPane(resultTextArea);
        constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.weighty = 1.0;
        constraints.weightx = 1.0;
        constraints.gridy = 3;
        add(resultScrollPane, constraints);
    }
}

P.S. Regarding the bottom component, wondering if it's better to show static results as a large label instead of a non-editable text area... couldn't find which is more "right" to do.


Solution

  • Two thingies, that appeared wrong to me, in the code pasted above as question ( IMHO ).

    1. The weightx/weighty both have values 1.0, when it should be different in terms of weighty, since each component is suppose to acquire different lengths on the parent container.
    2. gbc.fill is set to HORIZONTAL, which means on resizing the parent, the components will only resize in the horizontal direction. To me it would be more appropriate if the components will expand in both directions, instead of just one, for good visual appearance

    Here try this example:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class GridBagLayoutExample {
    
        private static final int GAP = 5;
        private GridBagConstraints gbc;
    
        private JTextArea insertQueryTextArea;
        private JTextArea resultTextArea;
        private JScrollPane scroller;
        private JButton executeQueryButton;
    
        public GridBagLayoutExample () {
            gbc = new GridBagConstraints ();
            gbc.anchor = GridBagConstraints.FIRST_LINE_START;
            gbc.insets = new Insets ( GAP, GAP, GAP, GAP );
            gbc.fill = GridBagConstraints.BOTH;
        }
    
        private void displayGUI () {
            JFrame frame = new JFrame ( "" );
            frame.setDefaultCloseOperation ( JFrame.DISPOSE_ON_CLOSE );
    
            JPanel contentPane = getPanel ();
            contentPane.setLayout ( new BorderLayout ( GAP, GAP) );
    
            JPanel containerPanel = getPanel ();
            containerPanel.setLayout ( new GridBagLayout () );
            addComponent ( 0, 0, 1, 1, 1.0, 0.1, containerPanel,
                new JLabel ( "Please inesrt your DML query here: ", JLabel.CENTER ) );
            insertQueryTextArea = getTextArea ();
            scroller = new JScrollPane ();
            scroller.setViewportView ( insertQueryTextArea );
            addComponent ( 0, 1, 1, 1, 1.0, 0.4, containerPanel, scroller );
            JPanel buttonPanel = getPanel ();
            executeQueryButton = new JButton ( "Execute Query" );
            buttonPanel.add ( executeQueryButton );
            addComponent ( 0, 2, 1, 1, 1.0, 0.1, containerPanel, buttonPanel );
            resultTextArea = getTextArea ();
            scroller = new JScrollPane ();
            scroller.setViewportView ( resultTextArea );
            addComponent ( 0, 3, 1, 1, 1.0, 0.4, containerPanel, scroller );
    
            contentPane.add ( containerPanel, BorderLayout.CENTER );
    
            frame.setContentPane ( contentPane );
            frame.pack ();
            frame.setLocationByPlatform ( true );
            frame.setVisible ( true );
        }
    
        private void addComponent ( int gridx, int gridy,
                                        int gridwidth, int gridheight,
                                        double weightx, double weighty,
                                        JComponent container, JComponent component ) {
            gbc.gridx = gridx;
            gbc.gridy = gridy;
            gbc.gridwidth = gridwidth;
            gbc.gridheight = gridheight;
            gbc.weightx = weightx;
            gbc.weighty = weighty;
    
            container.add ( component, gbc );
        }
    
        private JTextArea getTextArea () {
            JTextArea tArea = new JTextArea ( 10, 10 );
            tArea.setLineWrap ( true );
            tArea.setWrapStyleWord ( true );
    
            return tArea;
        }
    
        private JPanel getPanel () {
            JPanel panel = new JPanel ();
            panel.setOpaque ( true );
            panel.setBorder ( BorderFactory.createEmptyBorder ( GAP, GAP, GAP, GAP ) );
    
            return panel;
        }
    
        public static void main ( String [] args ) {
            Runnable runnable = new Runnable () {
                @Override
                public void run () {
                    new GridBagLayoutExample ().displayGUI ();
                }
            };
            EventQueue.invokeLater ( runnable );
        }
    }
    
    Regarding the bottom component, wondering if it's better to show static results as a large label instead of a non-editable text area... couldn't find which is more "right" to do.

    If scrolling the contents of the JTextArea is the idea behind the actual design, then surely a JTextArea to show the results will be an appropriate solution.

    Here is the output:

    GRIDBAGLAYOUT_EXAMPLE