Java JTextfield 不遵守给定的列宽

Java JTextfield not respecting given column width

我正在尝试制作一个表单,dataIn 面板将有一个标签,后跟相应的文本字段,供用户输入数据。

所以我发现 GridBagLayout 是最好的方法,但我还不知道如何使用它。

到目前为止,这是结果。我的整个窗体是 BorderLayout,但我们只关注它的北部,用户将在此处输入数据。

这个北部容器包含一个 4 行 2 列的 GridLayout。 在这个 GridLayout 的 (0,0) 内,我创建了另一个带有 GridBagLayout、JLabel 和 JTextfield 的面板。这个想法是让这个容器能够响应并填充现在显示为灰色的整个剩余区域,我希望它全部都是文本字段。

如果有人可以帮助我了解如何使用 GridBagLayout 执行此操作,我将不胜感激。我知道我做的可能不是最优的,所以我会听取更好的建议。

谢谢。

import java.awt.*;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import java.awt.Insets;
import java.awt.event.*;

@SuppressWarnings("serial")

public class UserForm extends JFrame {

    public UserForm() {

        // Miscelaneous
        Font font0 = new Font("Tahoma", Font.PLAIN, 12);
        Font font1 = new Font("Tahoma", Font.BOLD, 11);
        Font font2 = new Font("Tahoma", Font.BOLD, 12);

        // Frame layout -> north: data-in form, center: Jtable displayed, south:
        // buttons.
        JPanel mainP = new JPanel(new BorderLayout(5, 25));
        JPanel dataIn = new JPanel(new GridLayout(4, 2, 60, 3));
        JPanel displayT = new JPanel(new BorderLayout(0, 20));
        JPanel buttons = new JPanel(new GridLayout(0, 3, 10, 5));

        // Data-In Form Components
        JLabel idl = new JLabel("Id:");
        JLabel namel = new JLabel("Name:");
        JLabel ln1l = new JLabel("First Lastname:");
        JLabel ln2l = new JLabel("Second Lastname:");
        JLabel agl = new JLabel("Age:");
        JLabel adl = new JLabel("Address:");
        JLabel pnl = new JLabel("Phone Number:");
        JLabel eml = new JLabel("E-Mail:");
        JTextField idtf = new JTextField("");
        JTextField nametf = new JTextField("");
        JTextField ln1tf = new JTextField("");
        JTextField ln2tf = new JTextField("");
        JTextField agtf = new JTextField("");
        JTextField adtf = new JTextField("");
        JTextField pntf = new JTextField("");
        JTextField emtf = new JTextField("");

        // Data-In Form Containers
        JPanel dataId = new JPanel(new GridBagLayout());
        JPanel dataName = new JPanel(new GridBagLayout());
        JPanel dataLN1 = new JPanel(new GridBagLayout());
        JPanel dataLN2 = new JPanel(new GridBagLayout());
        JPanel dataAg = new JPanel(new GridBagLayout());
        JPanel dataAd = new JPanel(new GridBagLayout());
        JPanel dataPN = new JPanel(new GridBagLayout());
        JPanel dataEM = new JPanel(new GridBagLayout());

        // Components into individual containers
        // GridBagLayout Constraints label
        GridBagConstraints c1 = new GridBagConstraints();
        c1.gridx = 0;
        c1.gridy = 0;
        c1.gridwidth = 1; 
        c1.gridheight = 1;
        c1.weightx = 0.5;
        c1.anchor = GridBagConstraints.FIRST_LINE_START;
        c1.insets = new Insets(3,10,0,0);

        // GridBagLayout Constraints tf
        GridBagConstraints c2 = new GridBagConstraints();
        c2.gridx = 1;
        c2.gridy = 0;
        //c2.gridwidth = 4; 
        c2.gridheight = 1;
        c2.weightx = 0.5;
        c2.anchor = GridBagConstraints.WEST;
        c2.insets = new Insets(3,0,0,10);
        c2.fill = GridBagConstraints.HORIZONTAL;

        dataId.add(idl, c1);
        dataId.add(idtf, c2);
        dataName.add(namel, c1);
        dataName.add(nametf, c2);
        dataLN1.add(ln1l, c1);
        dataLN1.add(ln1tf, c2);
        dataLN2.add(ln2l, c1);
        dataLN2.add(ln2tf, c2);
        dataAg.add(agl, c1);
        dataAg.add(agtf, c2);
        dataAd.add(adl, c1);
        dataAd.add(adtf, c2);
        dataPN.add(pnl, c1);
        dataPN.add(pntf, c2);
        dataEM.add(eml, c1);
        dataEM.add(emtf, c2);

        // Miscelaneous
        idl.setFont(font2);
        idtf.setFont(font0);
        namel.setFont(font2);
        nametf.setFont(font0);
        ln1l.setFont(font2);
        ln1tf.setFont(font0);
        ln2l.setFont(font2);
        ln2tf.setFont(font0);
        agl.setFont(font2);
        agtf.setFont(font0);
        adl.setFont(font2);
        adtf.setFont(font0);
        pnl.setFont(font2);
        pntf.setFont(font0);
        eml.setFont(font2);
        emtf.setFont(font0);

        // Set tf editable
        idtf.setEditable(true);
        nametf.setEditable(true);
        ln1tf.setEditable(true);
        ln2tf.setEditable(true);
        agtf.setEditable(true);
        adtf.setEditable(true);
        pntf.setEditable(true);
        emtf.setEditable(true);

        dataIn.add(dataId);
        dataIn.add(dataAg);
        dataIn.add(dataName);
        dataIn.add(dataAd);
        dataIn.add(dataLN1);
        dataIn.add(dataPN);
        dataIn.add(dataLN2);
        dataIn.add(dataEM);

        // JTable Creation
        String[] headline = { "Id", "Name", "First Lastname", "Second Lastname", "Age", "Address", "Phone Number",
                "E-Mail" };
        String[][] data = { { "", "", "", "", "", "", "", "" }, { "", "", "", "", "", "", "", "" } };
        JTable dataShow = new JTable(data, headline);

        // Table Personalization
        dataShow.getTableHeader().setFont(font1);
        new HeaderRenderer(dataShow);

        // Add to container
        JPanel tableP = new JPanel(new BorderLayout(1, 1));
        tableP.add(dataShow.getTableHeader(), BorderLayout.NORTH);
        tableP.add(dataShow, BorderLayout.CENTER);
        JScrollPane sP = new JScrollPane();
        sP.setViewportView(tableP);
        displayT.add(sP, BorderLayout.CENTER);

        // buttons Components and Cointainers
        JButton save = new JButton("Save");
        JButton del = new JButton("Delete");
        JButton edit = new JButton("Edit");
        JLabel empty = new JLabel("");

        // Add to button panel
        buttons.add(save);
        buttons.add(del);
        buttons.add(edit);
        buttons.add(empty);

        // Miscelaneous
        save.setFont(font2);
        del.setFont(font2);
        edit.setFont(font2);

        // Add subpanels to main panel
        mainP.add(dataIn, BorderLayout.NORTH);
        mainP.add(displayT, BorderLayout.CENTER);
        mainP.add(buttons, BorderLayout.SOUTH);

        // set content pane
        setContentPane(mainP);
        setVisible(true);
        setTitle("User Form");
        setSize(900, 500);
        setResizable(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // For future table filling
        /*
         * String ids = idtf.getText(); String names = nametf.getText(); String ln1s =
         * ln1tf.getText(); String ln2s = ln2tf.getText(); String ags = agtf.getText();
         * String ads = adtf.getText(); String pns = pntf.getText(); String ems =
         * emtf.getText();
         */

    }

    public static void main(String[] args) {

        // invoke runnable for thread safety
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new UserForm();
            }
        });

    }

    // LEFT alignment renderer
    private class HeaderRenderer implements TableCellRenderer {

        DefaultTableCellRenderer renderer;

        public HeaderRenderer(JTable table) {
            renderer = (DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer();
            renderer.setHorizontalAlignment(JLabel.LEFT);
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                int row, int col) {
            return renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
        }

    }

}

这是我使用网格包布局创建的 GUI。

以下是我所做的主要更改。

  1. 我用的是JFrame。没有理由扩展 Swing 组件,除非您要重写 class 方法之一。

  2. 我按正确的顺序排列了 JFrame 方法。必须按照我在代码中输入的顺序调用 JFrame 方法。

  3. 我将每个 JComponent 的所有 JComponent 方法组合在一起,并按照它们在 JFrame 上出现的顺序创建了 JComponent。为了所有开发人员的爱心,始终按行、列顺序创建 JComponents。

  4. 除了 JTable 的首选视点大小外,我删除了所有大小调整。

  5. 我为每个 JComponent 定义了网格包约束。这样,您就可以调整每个 JComponent 的约束。此外,我不记得默认值。

此 GUI 中有两个 JPanel。主 JPanel 包含除 JButton 之外的所有 JComponent。第二个 JPanel 包含 JButton。这是因为有3个按钮,我把网格包布局分成了4列。

网格包布局使用 4 列。 JTable 占据所有 4 列,还有按钮 JPanel。

这是代码。

package com.ggl.testing;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;

public class UserForm {

    // top, left, bottom, right
    private static final Insets topInsets = new Insets(10, 10, 10, 10);
    private static final Insets topCenterInsets = new Insets(10, 0, 10, 10);
    private static final Insets middleInsets = new Insets(0, 10, 10, 10);
    private static final Insets middleCenterInsets = new Insets(0, 0, 10, 10);

    public UserForm() {

        JFrame frame = new JFrame("User Form");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Miscelaneous
        Font plain = new Font("Tahoma", Font.PLAIN, 12);
        Font bold11 = new Font("Tahoma", Font.BOLD, 11);
        Font bold12 = new Font("Tahoma", Font.BOLD, 12);

        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new GridBagLayout());

        int gridy = 0;

        // Data-In Form Components
        JLabel idl = new JLabel("Id:");
        idl.setFont(bold12);
        addComponent(mainPanel, idl, 0, gridy, 1, 1, topInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.NONE);

        JTextField idtf = new JTextField(40);
        idtf.setFont(plain);
        addComponent(mainPanel, idtf, 1, gridy, 1, 1, topCenterInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.HORIZONTAL);

        JLabel agl = new JLabel("Age:");
        agl.setFont(bold12);
        addComponent(mainPanel, agl, 2, gridy, 1, 1, topCenterInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.NONE);

        JTextField agtf = new JTextField(40);
        agtf.setFont(plain);
        addComponent(mainPanel, agtf, 3, gridy++, 1, 1, topCenterInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.HORIZONTAL);

        JLabel namel = new JLabel("Name:");
        namel.setFont(bold12);
        addComponent(mainPanel, namel, 0, gridy, 1, 1, middleInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.NONE);

        JTextField nametf = new JTextField(40);
        nametf.setFont(plain);
        addComponent(mainPanel, nametf, 1, gridy, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.HORIZONTAL);

        JLabel adl = new JLabel("Address:");
        adl.setFont(bold12);
        addComponent(mainPanel, adl, 2, gridy, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.NONE);

        JTextField adtf = new JTextField(40);
        adtf.setFont(plain);
        addComponent(mainPanel, adtf, 3, gridy++, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.HORIZONTAL);

        JLabel pnl = new JLabel("Phone Number:");
        pnl.setFont(bold12);
        addComponent(mainPanel, pnl, 0, gridy, 1, 1, middleInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.NONE);

        JTextField pntf = new JTextField(40);
        pntf.setFont(plain);
        addComponent(mainPanel, pntf, 1, gridy, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.HORIZONTAL);

        JLabel ln1l = new JLabel("First Lastname:");
        ln1l.setFont(bold12);
        addComponent(mainPanel, ln1l, 2, gridy, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.NONE);

        JTextField ln1tf = new JTextField(40);
        ln1tf.setFont(plain);
        addComponent(mainPanel, ln1tf, 3, gridy++, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.HORIZONTAL);

        JLabel ln2l = new JLabel("Second Lastname:");
        ln2l.setFont(bold12);
        addComponent(mainPanel, ln2l, 0, gridy, 1, 1, middleInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.NONE);

        JTextField ln2tf = new JTextField(40);
        ln2tf.setFont(plain);
        addComponent(mainPanel, ln2tf, 1, gridy, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.HORIZONTAL);

        JLabel eml = new JLabel("E-Mail:");
        eml.setFont(bold12);
        addComponent(mainPanel, eml, 2, gridy, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.NONE);

        JTextField emtf = new JTextField(40);
        emtf.setFont(plain);
        addComponent(mainPanel, emtf, 3, gridy++, 1, 1, middleCenterInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.HORIZONTAL);

        // JTable Creation
        String[] headline = { "Id", "Name", "First Lastname", "Second Lastname", "Age", "Address", "Phone Number",
                "E-Mail" };
        String[][] data = { { "", "", "", "", "", "", "", "" }, { "", "", "", "", "", "", "", "" } };
        JTable dataShow = new JTable(data, headline);
        dataShow.setPreferredScrollableViewportSize(new Dimension(900, 300));
        dataShow.setFillsViewportHeight(true);
        JScrollPane scrollPane = new JScrollPane(dataShow);
        addComponent(mainPanel, scrollPane, 0, gridy++, 4, 1, middleInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.HORIZONTAL);


        // Table Personalization
        dataShow.getTableHeader().setFont(bold11);
        new HeaderRenderer(dataShow);

        // buttons Components 
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new GridBagLayout());
        JButton save = new JButton("Save");
        save.setFont(bold12);
        addComponent(buttonPanel, save, 0, 0, 1, 1, topInsets, GridBagConstraints.CENTER,
                GridBagConstraints.HORIZONTAL);

        JButton del = new JButton("Delete");
        del.setFont(bold12);
        addComponent(buttonPanel, del, 1, 0, 1, 1, topInsets, GridBagConstraints.CENTER,
                GridBagConstraints.HORIZONTAL);

        JButton edit = new JButton("Edit");
        edit.setFont(bold12);
        addComponent(buttonPanel, edit, 2, 0, 1, 1, topInsets, GridBagConstraints.CENTER,
                GridBagConstraints.HORIZONTAL);

        addComponent(mainPanel, buttonPanel, 0, gridy++, 4, 1, middleInsets, GridBagConstraints.LINE_START,
                GridBagConstraints.HORIZONTAL);

        // set content pane
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

        // For future table filling
        /*
         * String ids = idtf.getText(); String names = nametf.getText(); String ln1s =
         * ln1tf.getText(); String ln2s = ln2tf.getText(); String ags = agtf.getText();
         * String ads = adtf.getText(); String pns = pntf.getText(); String ems =
         * emtf.getText();
         */

    }

    private void addComponent(Container container, Component component, int gridx, int gridy, int gridwidth,
            int gridheight, Insets insets, int anchor, int fill) {
        GridBagConstraints gbc = new GridBagConstraints(gridx, gridy, gridwidth, gridheight, 1.0, 1.0, anchor, fill,
                insets, 0, 0);
        container.add(component, gbc);
    }

    public static void main(String[] args) {

        // invoke runnable for thread safety
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new UserForm();
            }
        });

    }

    // LEFT alignment renderer
    private class HeaderRenderer implements TableCellRenderer {

        DefaultTableCellRenderer renderer;

        public HeaderRenderer(JTable table) {
            renderer = (DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer();
            renderer.setHorizontalAlignment(JLabel.LEFT);
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                int row, int col) {
            return renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
        }

    }

}

要使右侧列增长并占用可用 space,请修改 GridBagLayout 的列权重,使右侧列具有更高的权重:

    JPanel dataName = new JPanel();
    GridBagLayout gbl = new GridBagLayout();
    gbl.columnWidths = new int[]{0, 0};
    gbl.columnWeights = new double[]{0.0, 6.0};
    dataName.setLayout(gbl);

GridBagConstraints

    GridBagConstraints c1 = new GridBagConstraints();
    c1.gridx = 0;
    c1.gridy = 0;
    c1.gridwidth = 1;
    c1.gridheight = 1;
    c1.weightx = 1;
    c1.anchor = GridBagConstraints.LINE_START;
    c1.insets = new Insets(3,10,0,0);
    c1.fill = GridBagConstraints.NONE;

    GridBagConstraints c2 = new GridBagConstraints();
    c2.gridx = 1;
    c2.gridy = 0;
    c2.gridwidth = 1;
    c2.gridheight = 1;
    c2.weightx = 1;
    c2.anchor = GridBagConstraints.LINE_START;
    c2.insets = new Insets(3,0,0,10);
    c2.fill = GridBagConstraints.HORIZONTAL;

为了更简洁和模块化的实现,您可以引入一种方法:

private JPanel makeWhrapperPane(Component c1, Component c2, GridBagConstraints gbc1, GridBagConstraints gbc2){

    JPanel wrapper = new JPanel();
    GridBagLayout gbl= new GridBagLayout();
    gbl.columnWidths = new int[]{0, 0};
    gbl.columnWeights = new double[]{0.0, 6.0};
    wrapper.setLayout(gbl);
    wrapper.add(c1, gbc1);
    wrapper.add(c2, gbc2);

    return wrapper;
}

并使用它:JPanel dataName = makeWhrapperPane(namel, nametf, c1, c2);

以下是上述建议更改的完整实施:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;

public class UserForm extends JFrame {

    private static final Insets insets = new Insets(10, 10, 10, 10);
    private static final Font font0 = new Font("Tahoma", Font.PLAIN, 12);
    private static final Font font1 = new Font("Tahoma", Font.BOLD, 11);
    private static final Font font2 = new Font("Tahoma", Font.BOLD, 12);
    private final  GridBagConstraints gbc1, gbc2;

    public UserForm() {

        // Frame layout -> north: data-in form, center: Jtable displayed, south:
        // buttons.
        JPanel mainP = new JPanel(new BorderLayout(5, 25));
        JPanel dataIn = new JPanel(new GridLayout(4, 2, 60, 3));
        JPanel displayT = new JPanel(new BorderLayout(0, 20));
        JPanel buttons = new JPanel(new GridLayout(0, 3, 10, 5));

        // Data-In Form Components
        JLabel idl = makeLabel("Id:");
        JLabel namel = makeLabel("Name:");
        JLabel ln1l = makeLabel("First Lastname:");
        JLabel ln2l = makeLabel("Second Lastname:");
        JLabel agl = makeLabel("Age:");
        JLabel adl = makeLabel("Address:");
        JLabel pnl = makeLabel("Phone Number:");
        JLabel eml = makeLabel("E-Mail:");
        JTextField idtf = makeTextField();
        JTextField nametf = makeTextField();
        JTextField ln1tf = new JTextField("");
        JTextField ln2tf = new JTextField("");
        JTextField agtf = new JTextField("");
        JTextField adtf = new JTextField("");
        JTextField pntf = new JTextField("");
        JTextField emtf = new JTextField("");

        gbc1= new GridBagConstraints();
        gbc1.gridx = 0;
        gbc1.gridy = 0;
        gbc1.gridwidth = 1;
        gbc1.gridheight = 1;
        gbc1.weightx = 1;
        gbc1.anchor = GridBagConstraints.LINE_START;
        gbc1.insets = new Insets(3,10,0,0);
        gbc1.fill = GridBagConstraints.NONE;

        gbc2 = new GridBagConstraints();
        gbc2.gridx = 1;
        gbc2.gridy = 0;
        gbc2.gridwidth = 1;
        gbc2.gridheight = 1;
        gbc2.weightx = 1;
        gbc2.anchor = GridBagConstraints.LINE_START;
        gbc2.insets = new Insets(3,0,0,10);
        gbc2.fill = GridBagConstraints.HORIZONTAL;

        dataIn.add(makeWhrapperPane(idl, idtf));
        dataIn.add(makeWhrapperPane(agl, agtf));
        dataIn.add(makeWhrapperPane(namel, nametf));
        dataIn.add(makeWhrapperPane(adl, adtf));
        dataIn.add(makeWhrapperPane(ln1l, ln1tf));
        dataIn.add(makeWhrapperPane(pnl, pntf));
        dataIn.add(makeWhrapperPane(ln2l, ln2tf));
        dataIn.add(makeWhrapperPane(eml, emtf));

        // JTable Creation
        String[] headline = { "Id", "Name", "First Lastname", "Second Lastname", "Age", "Address", "Phone Number",
                "E-Mail" };
        String[][] data = { { "", "", "", "", "", "", "", "" }, { "", "", "", "", "", "", "", "" } };
        JTable dataShow = new JTable(data, headline);

        // Table Personalization
        dataShow.getTableHeader().setFont(font1);
        new HeaderRenderer(dataShow);

        // Add to container
        JPanel tableP = new JPanel(new BorderLayout(1, 1));
        tableP.add(dataShow.getTableHeader(), BorderLayout.NORTH);
        tableP.add(dataShow, BorderLayout.CENTER);
        JScrollPane sP = new JScrollPane();
        sP.setViewportView(tableP);
        displayT.add(sP, BorderLayout.CENTER);

        // buttons Components and Cointainers
        JButton save = makeButton("Save");
        JButton del = makeButton("Delete");
        JButton edit = makeButton("Edit");
        JLabel empty = new JLabel("");

        // Add to button panel
        buttons.add(save);
        buttons.add(del);
        buttons.add(edit);
        buttons.add(empty);

        // Add subpanels to main panel
        mainP.add(dataIn, BorderLayout.NORTH);
        mainP.add(displayT, BorderLayout.CENTER);
        mainP.add(buttons, BorderLayout.SOUTH);

        // set content pane
        setContentPane(mainP);
        setTitle("User Form");
        setSize(900, 500);
        setResizable(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    private JTextField makeTextField() {
        JTextField tf = new JTextField("");
        tf.setFont(font0);
        tf.setEditable(true);
        return tf;
    }

    private JLabel makeLabel(String s) {
        JLabel label = new JLabel(s);
        label.setFont(font2);
        return label;
    }

    private JButton makeButton(String s) {
        JButton button = new JButton(s);
        button.setFont(font2);
        return button;
    }

    private JPanel makeWhrapperPane(Component c1, Component c2){
        JPanel wrapper = new JPanel();
        GridBagLayout gbl= new GridBagLayout();
        gbl.columnWidths = new int[]{0, 0};
        gbl.columnWeights = new double[]{0.0, 6.0};
        wrapper.setLayout(gbl);
        wrapper.add(c1, gbc1);
        wrapper.add(c2, gbc2);
        return wrapper;
    }

    public static void main(String[] args) {
        // invoke runnable for thread safety
        SwingUtilities.invokeLater(() -> new UserForm());
    }

    // LEFT alignment renderer
    private class HeaderRenderer implements TableCellRenderer {

        DefaultTableCellRenderer renderer;
        public HeaderRenderer(JTable table) {
            renderer = (DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer();
            renderer.setHorizontalAlignment(JLabel.LEFT);
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                int row, int col) {
            return renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
        }
    }
}