javaswinglayout-manager

Rendering properly using GridBagLayout


In the screenshot attached, I have a JLabel, JTextField and a JTabel wrapped in a JSchrollPane. First of all, the JLabel and JTextField are floating so far down in the middle. There is a lot of space on top. I want to close that space. Secondly, I want the JTable/JSchrollPane to fill the entire width. It only takes up half the width. And it doesn't show the 3 rows that the table contains.

If I do this instead panFindStudent.add(table, gbcFindStud); the rows show, but it still doesn't look pretty. And I want to use the JSchrollPane, so that it is possible to schroll, if the table contains many rows/cols

I also tried wrapping the JLabel and JTexField in a JPanel for itself, and the JSchrollPane in another JPanel, and then adding those 2 JPanels to separately the JFrame like this

findStudentFrame.add(panelWithLabelAndTextField)
findStudentFrame.add(paneLWithShcrollPane)

but doing that, only the last panel seems to be added, not the first one

I eventually also ended up thinking that GridBagLayout may not be the right choice for this task, and I tried with a mixture of GridBagLayout and FlowLayout. It gave better results, but still not satisfying. But I'm thinking it's better to learn fix this with the GridBagLayout, so that I learn using it properly. You're welcome to suggest ways to make my result/look better. I have added my entire code at the bottom, so you can run it, and change it. Thanks

enter image description here

I want something similaar to this enter image description here

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Toolkit;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;

public class SwingPractice2 {
    
    private JFrame findStudentFrame;
    private JPanel panFindStudent, panTableResults;
    private JLabel labelAddStudEmail;
    private JTextField tFieldAddStudFirstName;
    
    private int textFieldWidth = 20,
            textFieldHeight = 10;
    
    private Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 

    private int frameWidth = screenSize.width/4, 
            frameHeight = screenSize.height/3;
    
    public SwingPractice2() {
        findStudentFrame = new JFrame();
        //findStudentFrame.setLayout(new GridLayout(2, 1));
        //findStudentFrame.setSize(frameWidth, frameHeight);
        //addStudentFrame.setSize(frameWidth, frameHeight);
        panFindStudent = new JPanel(new GridBagLayout());
        panFindStudent.setPreferredSize(new Dimension(frameWidth, frameHeight));
        panFindStudent.setBorder(BorderFactory.createTitledBorder("Students"));
        
        labelAddStudEmail = new JLabel("Email");    
        tFieldAddStudFirstName = new JTextField();
        tFieldAddStudFirstName.setSize(textFieldWidth, textFieldHeight);
        
        panTableResults = new JPanel(new FlowLayout());
    }

    public void showStudentGUI() {
        GridBagConstraints gbcFindStud = new GridBagConstraints();
        gbcFindStud.anchor = GridBagConstraints.NORTHWEST;      
        gbcFindStud.gridx = 0;
        gbcFindStud.gridy = 0;
        gbcFindStud.weightx = 1.0;
        gbcFindStud.fill = GridBagConstraints.HORIZONTAL;
        gbcFindStud.insets = new Insets(5, 5, 5, 5);
        
        panFindStudent.add(labelAddStudEmail, gbcFindStud);
                
        gbcFindStud.gridx++;
        gbcFindStud.anchor = GridBagConstraints.NORTHEAST;
        panFindStudent.add(tFieldAddStudFirstName, gbcFindStud);
        
        String[] tableCols = new String[] {
            "ID", "First name", "Last name" 
        };
        
        String data[][] = {
                {"1", "Marcus", "Johnson" }, 
                {"2", "Miko", "Jameson"},
                {"2", "Kate", "Anderson"}
        };
        
        JTable table = new JTable(data, tableCols);     
        //table.setBounds(30, 40, 200, 300);
        
        JScrollPane jsp = new JScrollPane(table);   
        //jsp.setBounds(30, 40, 300, 300);
        
        gbcFindStud.gridx = 0;
        gbcFindStud.gridy = 1;
        gbcFindStud.fill = GridBagConstraints.HORIZONTAL;
        gbcFindStud.anchor = GridBagConstraints.CENTER;
                
        panFindStudent.add(jsp, gbcFindStud);
        
        findStudentFrame.add(panFindStudent);
        //findStudentFrame.add(jsp);
        findStudentFrame.pack();
        findStudentFrame.setVisible(true);
    }
    
    public static void main(String[] args) {
        new SwingPractice2().showStudentGUI();
    }

}

Solution

  • First, some advice...

    private Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    

    isn't the best way to get the "viewable" area of the display, it will not take into account the size or position of things like the dock/menu bars on most OS's which could cause you issues.

    Personally, I'd avoid using setPreferredSize, this could have future ramifications on your layouts.

    This...

    tFieldAddStudFirstName.setSize(textFieldWidth, textFieldHeight);
    

    is also irrelevant.

    On to your problems...

    First, gbcFindStud.weightx = 1.0; is giving me issues. Instead, for the Email label, I would just use...

    gbcFindStud.anchor = GridBagConstraints.EAST;
    gbcFindStud.gridx = 0;
    gbcFindStud.gridy = 0;
    gbcFindStud.insets = new Insets(5, 5, 5, 5);
    

    This ensures that the label is only as big as it needs to be, why? Because you want the text field to be aligned to it so that there is a visual correlation between the two elements.

    For the text field, I would use...

    gbcFindStud.gridx++;
    gbcFindStud.fill = GridBagConstraints.HORIZONTAL;
    gbcFindStud.weightx = 1.0;
    panFindStudent.add(tFieldAddStudFirstName, gbcFindStud);
    

    This ensures that the text field fills all the remaining space horizontally, not sure how bug some ones email might be, but it's nice to be able to read what you've typed in a single glance.

    For the table, I would use...

    gbcFindStud.gridx = 0;
    gbcFindStud.gridy = 1;
    gbcFindStud.gridwidth = GridBagConstraints.REMAINDER;
    gbcFindStud.fill = GridBagConstraints.BOTH;
    gbcFindStud.weighty = 1;
    

    The important part here is gbcFindStud.gridwidth = GridBagConstraints.REMAINDER. This ensures that the table will expand all the remaining columns. I also added gbcFindStud.weighty = 1 to ensure it will fill the remaining vertical space (and push the other elements to the top of the view)

    This now generates...

    enter image description here

    You still need to put in the All Students label, but based on the information I've provided above, you should be able to figure it out. Don't forget to reference How to Use GridBagLayout

    Don't forget, you can make use of multiple containers, making use of different layout managers.

    For example, the email label and text field could be a separate container, which could then be added to a container using a BorderLayout, simplifying the logic.

    Runnable example...

    import java.awt.EventQueue;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    import javax.swing.BorderFactory;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.JTextField;
    
    public class Main {
    
        public static void main(String[] args) {
            new Main();
        }
    
        public Main() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new SwingPractice2().showStudentGUI();
                }
            });
        }
    
        public class SwingPractice2 {
    
            private JFrame findStudentFrame;
            private JPanel panFindStudent, panTableResults;
            private JLabel labelAddStudEmail;
            private JTextField tFieldAddStudFirstName;
    
            public SwingPractice2() {
                findStudentFrame = new JFrame();
                panFindStudent = new JPanel(new GridBagLayout());
                panFindStudent.setBorder(BorderFactory.createTitledBorder("Students"));
    
                labelAddStudEmail = new JLabel("Email");
                tFieldAddStudFirstName = new JTextField();
            }
    
            public void showStudentGUI() {
                GridBagConstraints gbcFindStud = new GridBagConstraints();
                gbcFindStud.anchor = GridBagConstraints.EAST;
                gbcFindStud.gridx = 0;
                gbcFindStud.gridy = 0;
                gbcFindStud.insets = new Insets(5, 5, 5, 5);
    
                panFindStudent.add(labelAddStudEmail, gbcFindStud);
    
                gbcFindStud.gridx++;
                gbcFindStud.fill = GridBagConstraints.HORIZONTAL;
                gbcFindStud.weightx = 1.0;
                panFindStudent.add(tFieldAddStudFirstName, gbcFindStud);
    
                String[] tableCols = new String[]{
                    "ID", "First name", "Last name"
                };
    
                String data[][] = {
                    {"1", "Marcus", "Johnson"},
                    {"2", "Miko", "Jameson"},
                    {"2", "Kate", "Anderson"}
                };
    
                JTable table = new JTable(data, tableCols);
    
                JScrollPane jsp = new JScrollPane(table);
    
                gbcFindStud.gridx = 0;
                gbcFindStud.gridy = 1;
                gbcFindStud.gridwidth = GridBagConstraints.REMAINDER;
                gbcFindStud.fill = GridBagConstraints.BOTH;
                gbcFindStud.weighty = 1;
    
                panFindStudent.add(jsp, gbcFindStud);
    
                findStudentFrame.add(panFindStudent);
                findStudentFrame.pack();
                findStudentFrame.setVisible(true);
            }
        }
    }