gridbaglayout putting second item in the center

469 Views Asked by At

am making an application in which i want to add text fields to a scroll pane, am using GridBagLayout and the problem am encountering is that the first text field i add is added at the top of the panel inside the scroll pane, but then, from the second on, they're added at the center, this is my code:

public class main extends javax.swing.JFrame {
private static HashMap<String, Integer> anch_codes = new HashMap<String, Integer>();
private static List<Component> items = new ArrayList<>();
/**
 * Creates new form main

 */
public main() {
    initComponents();
}
/**
 * This method is called from within the constructor to initialize the form.
 * WARNING: Do NOT modify this code. The content of this method is always
 * regenerated by the Form Editor.
 */
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    jMenuBar1 = new javax.swing.JMenuBar();
    jMenu1 = new javax.swing.JMenu();
    jMenuItem1 = new javax.swing.JMenuItem();
    jMenu2 = new javax.swing.JMenu();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    jMenu1.setText("File");

    jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
    jMenuItem1.setLabel("Save");
    jMenu1.add(jMenuItem1);
    jMenuItem1.getAccessibleContext().setAccessibleName("save_opt");

    jMenuBar1.add(jMenu1);

    jMenu2.setText("Edit");
    jMenuBar1.add(jMenu2);

    setJMenuBar(jMenuBar1);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGap(0, 1282, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGap(0, 703, Short.MAX_VALUE)
    );

    pack();
}// </editor-fold>                        

/**
 * @param args the command line arguments
 */
public static void main(String args[]) {
    /* Set the Nimbus look and feel */
    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
    /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
     * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */
    try {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException ex) {
        java.util.logging.Logger.getLogger(main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
        java.util.logging.Logger.getLogger(main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        java.util.logging.Logger.getLogger(main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    //</editor-fold>

    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            setAnchCodes();
            JFrame fmain = new main();

            fmain.setLayout(new GridBagLayout());
            GridBagConstraints c = new GridBagConstraints();

            fmain.setExtendedState(JFrame.MAXIMIZED_BOTH); 

            JTextField maintext = new JTextField();
            addToGrid(c, fmain, maintext, 0, 0, 0.9, 1.0, anch_codes.get("FIRST_LINE_START"));

            JButton add_btn =  new JButton("Add");
            addToGrid(c, fmain, add_btn, 1, 0, 0.1, 1.0, anch_codes.get("FIRST_LINE_START"));

            JPanel scrpanel = new JPanel(new GridBagLayout());
            scrpanel.setBackground(Color.WHITE);
            JScrollPane display_area = new JScrollPane(scrpanel);
            display_area.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
            display_area.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            addToGrid(c, fmain, display_area, 0, 1, 1.0, 1000, anch_codes.get("FIRST_LINE_START"), 2);

            GridBagConstraints an_c = new GridBagConstraints();
            eventAddNew(an_c, add_btn,maintext,scrpanel,fmain,display_area);

            fmain.setVisible(true);

        }
    });
}

public static void eventAddNew(GridBagConstraints c, Component ... comp) {
    JButton add_btn = (JButton) comp[0];
    JTextField maintext = (JTextField) comp[1];
    JPanel scrpanel = (JPanel) comp[2];
    JFrame fmain = (JFrame) comp[3];
    JScrollPane display_area = (JScrollPane) comp[4];
    add_btn.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            JTextField item = new JTextField(maintext.getText());
            item.setEnabled(false);
            item.setEditable(false);
            addToGrid(c, scrpanel, item, 0, items.size(), 1.0, 1.0, anch_codes.get("FIRST_LINE_START"));
            items.add(item);
            fmain.repaint();
            fmain.revalidate();
            display_area.repaint();
            display_area.revalidate();
        }
    });
}

public static void addToGrid(GridBagConstraints c, Component parent, Component child, int x, int y, double weightx, double weighty, int anchor){

    String fcls = parent.getClass().toString();
    String cls = fcls.substring(fcls.lastIndexOf(".")+1);

    c.fill = GridBagConstraints.HORIZONTAL;
    c.anchor = anchor;
    c.weightx = weightx;
    c.weighty = weighty;
    c.gridx = x;
    c.gridy = y;

    if ("JFrame".equals(cls) || "main".equals(cls)) {
        JFrame frame = (JFrame) parent;
        frame.add(child,c);
    } else if ("JPanel".equals(cls)) {
        JPanel panel = (JPanel) parent;
        panel.add(child, c);
    }
}

public static void addToGrid(GridBagConstraints c, JFrame frame, Component element, int x, int y, double weightx, double weighty, int anchor, int gridwidth){

    String fcls = element.getClass().toString();
    String cls = fcls.substring(fcls.lastIndexOf(".")+1);


    c.anchor = anchor;
    c.weightx = weightx;
    c.weighty = weighty;
    c.gridx = x;
    c.gridy = y;
    c.gridwidth = gridwidth;
    if ("JScrollPane".equals(cls)) {
        c.fill = GridBagConstraints.BOTH;
    } else {
        c.fill = GridBagConstraints.HORIZONTAL;
    }
    frame.add(element,c);
}

private static void setAnchCodes() {
    anch_codes.put("FIRST_LINE_START", 23);
    anch_codes.put("FIRST_LINE_END", 24);
}

// Variables declaration - do not modify                     
private javax.swing.JMenu jMenu1;
private javax.swing.JMenu jMenu2;
private javax.swing.JMenuBar jMenuBar1;
private javax.swing.JMenuItem jMenuItem1;
// End of variables declaration                   
}

I was having the same problem with the outer frame that also has grid bag layout but I worked around it by setting weighty to a high value, but this doesn't work for the case in question and probably is not the right way to do it. If any one can provide any advice it would be of great help.

1

There are 1 best solutions below

1
On BEST ANSWER

You don't need to use GridBagLayout for this, and I suggest that you don't. Instead create a JPanel that uses GridLayout(0, 1) for a Grid that has 1 column and any number of rows. Then -- and this is key -- place this JPanel into another JPanel that uses BorderLayout, into the BorderLayout.PAGE_START position, so that it is always on top. Then place this border layout-using JPanel into your JScrollPane.

For example:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;

import javax.swing.*;

public class AddComponents extends JPanel {
    private static final int PREF_W = 600;
    private static final int PREF_H = 450;
    private JTextField inputField = new JTextField(20);
    private AddAction addAction = new AddAction("Add");
    private JButton addButton = new JButton(addAction);
    private JPanel innerPanel = new JPanel(new GridLayout(0, 1)); // 1 column, any number of rows

    public AddComponents() {
        JPanel borderLayoutPanel = new JPanel(new BorderLayout());
        borderLayoutPanel.add(innerPanel, BorderLayout.PAGE_START);
        JScrollPane scrollPane = new JScrollPane(borderLayoutPanel);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        inputField.setAction(addAction);
        JPanel topPanel = new JPanel();
        topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.LINE_AXIS));
        topPanel.add(inputField);
        topPanel.add(addButton);

        setLayout(new BorderLayout());
        add(scrollPane);
        add(topPanel, BorderLayout.PAGE_START);
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension prefSize = super.getPreferredSize();
        if (isPreferredSizeSet()) {
            return prefSize;
        } else {
            int w = Math.max(PREF_W, prefSize.width);
            int h = Math.max(PREF_H, prefSize.height);
            return new Dimension(w, h);
        }
    }

    private class AddAction extends AbstractAction {
        public AddAction(String name) {
            super(name);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            String text = inputField.getText();
            JTextField innerTextField = new JTextField(text);
            innerPanel.add(innerTextField);
            revalidate();
            repaint();
            inputField.selectAll();
            inputField.requestFocusInWindow();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui() {
        AddComponents mainPanel = new AddComponents();
        JFrame frame = new JFrame("Add Components");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

But having shown this, if you want to display JTextField equivalents, ones that may or may not be editable, depending on your desire, then use a simple JTable instead.

For example:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;

public class AddItems extends JPanel {
    private static final int PREF_W = 600;
    private static final int PREF_H = 450;
    private JTextField inputField = new JTextField(20);
    private AddToTableAction addAction = new AddToTableAction("Add");
    private JButton addButton = new JButton(addAction);
    private DefaultTableModel tableModel = new DefaultTableModel(new String[]{"A"}, 0);
    private JTable table = new JTable(tableModel){
        public boolean isCellEditable(int row, int column) {
            return false;
        };
    };

    public AddItems() {
        table.setTableHeader(null);
        JScrollPane scrollPane = new JScrollPane(table);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        inputField.setAction(addAction);
        JPanel topPanel = new JPanel();
        topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.LINE_AXIS));
        topPanel.add(inputField);
        topPanel.add(addButton);

        setLayout(new BorderLayout());
        add(scrollPane);
        add(topPanel, BorderLayout.PAGE_START);
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension prefSize = super.getPreferredSize();
        if (isPreferredSizeSet()) {
            return prefSize;
        } else {
            int w = Math.max(PREF_W, prefSize.width);
            int h = Math.max(PREF_H, prefSize.height);
            return new Dimension(w, h);
        }
    }

    private class AddToTableAction extends AbstractAction {
        public AddToTableAction(String name) {
            super(name);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            String text = inputField.getText();
            tableModel.addRow(new String[] {text});
            inputField.selectAll();
            inputField.requestFocusInWindow();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui() {
        AddItems mainPanel = new AddItems();
        JFrame frame = new JFrame("AddItems");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
}