简体   繁体   中英

How can I resize my JTextFields in my Jpanel

being new to programming, i'm having a slight issue resizing the text fields I've added to the JPanel. While I could go the route of creating individual panels with their own text field, I though it would be better to add all the components into one panel. Part of my overall idea is to have my add button reference the panel, containing the text fields, to add more text fields on the tracker for users to fill out, and while I can get the fields to display when I implement the setBounds method on my panel object, i'm having tough time figuring out how resize them in the panel itself. And if you have any other advice on my overall structure, I welcome it.

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;


public class UI {
JFrame frame;
JLabel Title,Name, CheckOut, CheckIn, Email;
JTextField NameField,CheckOutField, CheckInField, EmailField;
JButton Add, Delete;
JPanel buttons, textfields, primary;

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                UI window = new UI();
                window.frame.setVisible(true);


            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
    }

public UI(){
    design();

}

 private void design(){


frame = new JFrame("Form 48 Tracker");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(100, 100, 750, 400);
frame.getContentPane().setLayout(null);


Title = new JLabel();
Title.setText("Form 48 Tracker");   
Title.setFont(new Font("Calibri", Font.PLAIN, 28));
Title.setBounds(233, 11, 200, 75);
frame.getContentPane().add(Title);
Title.setForeground(Color.BLACK);

Name = new JLabel();
Name.setText("Name");   
Name.setFont(new Font("Calibri", Font.PLAIN, 15));
Name.setBounds(50, 80, 128, 20);
frame.getContentPane().add(Name);
Name.setForeground(Color.BLACK);

CheckOut = new JLabel();
CheckOut.setText("Check Out Date"); 
CheckOut.setFont(new Font("Calibri", Font.PLAIN, 15));
CheckOut.setBounds(200, 80, 128, 20);
frame.getContentPane().add(CheckOut);
CheckOut.setForeground(Color.BLACK);

CheckIn = new JLabel();
CheckIn.setText("Check In Date");   
CheckIn.setFont(new Font("Calibri", Font.PLAIN, 15));
CheckIn.setBounds(350, 80, 128, 20);
frame.getContentPane().add(CheckIn);
CheckIn.setForeground(Color.BLACK);

Email = new JLabel();
Email.setText("Email"); 
Email.setFont(new Font("Calibri", Font.PLAIN, 15));
Email.setBounds(500, 80, 128, 20);
frame.getContentPane().add(Email);
Email.setForeground(Color.BLACK);


Add = new JButton("Add");
buttons = new JPanel();
buttons.add(Add);
buttons.setBounds(200, 270, 157, 50); //x , y , width , height//
frame.getContentPane().add(buttons);
Add.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e){


    }
});

Delete = new JButton("Delete");
buttons = new JPanel();
buttons.add(Delete);
buttons.setBounds(605, 101, 128, 50);
frame.getContentPane().add(buttons);



primary = new JPanel();
NameField = new JTextField();
CheckOutField = new JTextField();
CheckInField = new JTextField();
EmailField = new JTextField();
primary.add(NameField);
primary.add(CheckOutField);
primary.add(CheckInField);
primary.add(EmailField);
primary.setBounds(50, 110, 128, 20);
frame.getContentPane().add(primary);

    }


 }

Let's concentrate on the code that's causing the problem, and only that code . I've created a minimal example program, one that has enough code to compile and run, and that demonstrates the problem, but that has no unnecessary code:

import javax.swing.*;

public class UiFoo {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Foo");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(null);  // **** no!! ****

            JPanel primary = new JPanel();
            JTextField NameField = new JTextField();
            JTextField CheckOutField = new JTextField();
            JTextField CheckInField = new JTextField();
            JTextField EmailField = new JTextField();
            primary.add(NameField);
            primary.add(CheckOutField);
            primary.add(CheckInField);
            primary.add(EmailField);
            primary.setBounds(50, 110, 128, 20);

            frame.getContentPane().add(primary);

            frame.setSize(600, 250);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}

So, if you run this code, you'll see 4 very small JTextFields. Why are they so small? Because you've not set the columns property for the JTextFields, and so they default to columns size 0 and show up like so:

在此处输入图片说明

So it's better if you can give the JTextField a columns property so that they have some width, eg, make this change:

JPanel primary = new JPanel();
int columns = 8;
JTextField NameField = new JTextField(columns);
JTextField CheckOutField = new JTextField(columns);
JTextField CheckInField = new JTextField(columns);
JTextField EmailField = new JTextField();

But this just shows one JTextField, and cuts off the bottom as well:

在此处输入图片说明

Why? Because you're artificially constraining the size of the containing JPanel, primary via:

primary.setBounds(50, 110, 128, 20);

This containing JPanel is only 128 pixels wide by 20 pixels high, meaning that it won't even display one JTextField well.

One solution is to use a mix of layout managers and JPanels as well as a JScrollPane to allow for a grid of JPanels to be added, something like so (try it out!):

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;

@SuppressWarnings("serial")
public class UiFoo2 extends JPanel {
    JPanel singleColumnPanel = new JPanel(new GridLayout(0, 1, 2, 2));

    public UiFoo2() {
        JButton addButton = new JButton("Add");
        addButton.addActionListener(e -> {
            JPanel rowPanel = new JPanel(new GridLayout(1, 4, 2, 2));
            for (int i = 0; i < 4; i++) {
                rowPanel.add(new JTextField(8));
            }

            singleColumnPanel.add(rowPanel);
            singleColumnPanel.revalidate();
            singleColumnPanel.repaint();
        });
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(addButton);

        JPanel labelPanel = new JPanel(new GridLayout(1, 4, 2, 2));
        labelPanel.add(new JLabel("Name", SwingConstants.CENTER));
        labelPanel.add(new JLabel("Check Out Date", SwingConstants.CENTER));
        labelPanel.add(new JLabel("Check In Date", SwingConstants.CENTER));
        labelPanel.add(new JLabel("Email", SwingConstants.CENTER));

        singleColumnPanel.add(labelPanel);

        JPanel containerPanel = new JPanel(new BorderLayout(5, 5));
        containerPanel.add(singleColumnPanel, BorderLayout.PAGE_START);
        JScrollPane scrollPane = new JScrollPane(containerPanel);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        setPreferredSize(new Dimension(650, 400));
        setLayout(new BorderLayout());
        add(scrollPane, BorderLayout.CENTER);
        add(buttonPanel, BorderLayout.PAGE_END);
    }

    private static void createAndShowGui() {
        UiFoo2 mainPanel = new UiFoo2();

        JFrame frame = new JFrame("UiFoo2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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

This will create a row JPanel that holds four JTextFields that get added to the JScrollPane when the add JButton is pressed, and looks like so:

在此处输入图片说明

but we still can do better. Why not instead create a class to hold a row of data, something like so:

import java.util.Date;

public class Form48Customer {
    private String name;
    private Date checkIn;
    private Date checkOut;
    private String Email;

    public Form48Customer(String name, Date checkIn, Date checkOut, String email) {
        this.name = name;
        this.checkIn = checkIn;
        this.checkOut = checkOut;
        Email = email;
    }

    public Date getCheckIn() {
        return checkIn;
    }

    public void setCheckIn(Date checkIn) {
        this.checkIn = checkIn;
    }

    public Date getCheckOut() {
        return checkOut;
    }

    public void setCheckOut(Date checkOut) {
        this.checkOut = checkOut;
    }

    public String getName() {
        return name;
    }

    public String getEmail() {
        return Email;
    }

    // should override hashCode and equals here

}

and then create a JTable complete with custom model to display objects of this type, and then display them in the GUI. This is much cleaner, more flexible, and extendable. Something like so:

import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.*;
import java.util.Date;
import javax.swing.*;
import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.table.*;

@SuppressWarnings("serial")
public class Form48TrackerPanel extends JPanel {
    public static final String TITLE = "Form 48 Tracker";
    private static final String DATE_FORMAT_TXT = "MM/dd/yyyy";
    private Form48TableModel model = new Form48TableModel();
    private JTable table = new JTable(model);
    private JButton addButton = new JButton("Add");
    private JButton deleteButton = new JButton("Delete");
    private JButton exitButton = new JButton("Exit");

    public Form48TrackerPanel() {
        final SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_TXT);
        TableCellRenderer dateRenderer = new DefaultTableCellRenderer() {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value,
                    boolean isSelected, boolean hasFocus, int row, int column) {
                if( value instanceof Date) {
                    value = dateFormat.format(value);
                }
                return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            }
        };
        table.getColumnModel().getColumn(1).setCellRenderer(dateRenderer);
        table.getColumnModel().getColumn(2).setCellRenderer(dateRenderer);
        JLabel titleLabel = new JLabel(TITLE, SwingConstants.CENTER);
        titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 28f));

        addButton.addActionListener(new AddListener());
        addButton.setMnemonic(KeyEvent.VK_A);
        deleteButton.addActionListener(new DeleteListener());
        deleteButton.setMnemonic(KeyEvent.VK_D);
        exitButton.addActionListener(new ExitListener());
        exitButton.setMnemonic(KeyEvent.VK_X);

        JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 0));
        buttonPanel.add(addButton);
        buttonPanel.add(deleteButton);
        buttonPanel.add(exitButton);

        setPreferredSize(new Dimension(800, 500));
        int ebGap = 8;
        setBorder(BorderFactory.createEmptyBorder(ebGap, ebGap, ebGap, ebGap));
        setLayout(new BorderLayout(ebGap, ebGap));
        add(titleLabel, BorderLayout.PAGE_START);
        add(new JScrollPane(table), BorderLayout.CENTER);
        add(buttonPanel, BorderLayout.PAGE_END);

        model.addRow(new Form48Customer("John Smith", new Date(), new Date(), "JSmith@Yahoo.com"));
        model.addRow(new Form48Customer("Fred Flinstone", new Date(), new Date(), "FFlinstone@GMail.com"));
    }

    private class AddListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            AddForm48Panel addFormPanel = new AddForm48Panel();
            int result = JOptionPane.showConfirmDialog(Form48TrackerPanel.this, 
                    addFormPanel, "Add Customer", JOptionPane.OK_CANCEL_OPTION, 
                    JOptionPane.PLAIN_MESSAGE);
            if (result == JOptionPane.OK_OPTION) {
                Form48Customer customer = addFormPanel.getForm48Customer();
                model.addRow(customer);
            }
        }
    }

    private class DeleteListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO *** finish this code ***

        }
    }

    private class ExitListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            Window win = SwingUtilities.getWindowAncestor(Form48TrackerPanel.this);
            win.dispose();
        }
    }

    private static void createAndShowGui() {
        Form48TrackerPanel mainPanel = new Form48TrackerPanel();

        JFrame frame = new JFrame(TITLE);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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

@SuppressWarnings("serial")
class AddForm48Panel extends JPanel {
    private static final int TFIELD_COLS = 10;
    private static final String DATE_FORMAT_TXT = "MM/dd/yyyy";
    private static final Format DATE_FORMAT = new SimpleDateFormat(DATE_FORMAT_TXT);
    private static final Insets INSETS = new Insets(5, 5, 5, 5);
    private JTextField nameField = new JTextField(TFIELD_COLS);
    private JFormattedTextField checkOutDateField = new JFormattedTextField(DATE_FORMAT);
    private JFormattedTextField checkInDateField = new JFormattedTextField(DATE_FORMAT);
    private JTextField emailField = new JTextField(TFIELD_COLS);
    private JComponent[] fields = {nameField, checkOutDateField, checkInDateField, emailField};
    private String[] labels = {"Name", "Check Out Date", "Check In Date", "Email"};

    public AddForm48Panel() {
        InputVerifier verifier = new DateFieldVerifier();
        checkInDateField.setInputVerifier(verifier);
        checkOutDateField.setInputVerifier(verifier);

        setLayout(new GridBagLayout());
        for (int i = 0; i < fields.length; i++) {
            add(new JLabel(labels[i] + ":"), createGbc(0, i));
            add(fields[i], createGbc(1, i));
        }
    }

    public String getName() {
        return nameField.getText();
    }

    public String getEmail() {
        return emailField.getText();
    }

    public Date getCheckOut() {
        return (Date) checkOutDateField.getValue();
    }

    public Date getCheckIn() {
        return (Date) checkInDateField.getValue();
    }

    public Form48Customer getForm48Customer() {
        String name = getName();
        Date checkOut = getCheckOut();
        Date checkIn = getCheckIn();
        String email = getEmail();
        return new Form48Customer(name, checkIn, checkOut, email);
    }

    private GridBagConstraints createGbc(int x, int y) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = x;
        gbc.gridy = y;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.insets = INSETS;
        gbc.anchor = x == 0 ? GridBagConstraints.WEST :GridBagConstraints.EAST;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        return gbc;
    }

    private class DateFieldVerifier extends InputVerifier {

        @Override
        public boolean verify(JComponent input) {
            if (input instanceof JFormattedTextField) {
                JFormattedTextField ftf = (JFormattedTextField)input;
                AbstractFormatter formatter = ftf.getFormatter();
                if (formatter != null) {
                    String text = ftf.getText();
                    try {
                         formatter.stringToValue(text);
                         return true;
                     } catch (ParseException pe) {
                         return false;
                     }
                 }
             }
             return true;
        }

        @Override
        public boolean shouldYieldFocus(JComponent input) {
            boolean verify = verify(input);
            if (!verify) {
                String message = "Enter a valid date, e.g.: 01/05/2017";
                String title = "Invalid Date Format";
                int type = JOptionPane.ERROR_MESSAGE;
                JOptionPane.showMessageDialog(input, message, title, type);
            }
            return verify;
        }        
    }
}

@SuppressWarnings("serial")
class Form48TableModel extends DefaultTableModel {
    private static final String[] COL_NAMES = {"Name", "Check Out Date", "Check In Date", "Email"};

    public Form48TableModel() {
        super(COL_NAMES, 0);
    }

    public void addRow(Form48Customer customer) {
        Object[] rowData = {
                customer.getName(),
                customer.getCheckOut(),
                customer.getCheckIn(),
                customer.getEmail()
        };
        addRow(rowData);
    }

    public Form48Customer getRow(int row) {
        String name = (String) getValueAt(row, 0);
        Date checkIn = (Date) getValueAt(row, 1);
        Date checkOut = (Date) getValueAt(row, 2);
        String email = (String) getValueAt(row, 3);
        return new Form48Customer(name, checkIn, checkOut, email);
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
        case 1:
            return Date.class;
        case 2:
            return Date.class;

        default:
            break;
        }
        return super.getColumnClass(columnIndex);
    }
}

Which would look like:

在此处输入图片说明

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