如何在Jpanel中调整JTextField的大小

时间:2017-11-12 14:16:27

标签: java swing user-interface

对编程不熟悉,我在调整我添加到JPanel的文本字段时遇到了轻微的问题。虽然我可以使用自己的文本字段创建单独的面板,但我将所有组件添加到一个面板中会更好。我的整体想法的一部分是让我的添加按钮引用包含文本字段的面板,在跟踪器上添加更多文本字段供用户填写,同时我可以在我实现setBounds方法时显示字段我的面板对象,我很难搞清楚如何在面板中调整它们的大小。如果您对我的整体结构有任何其他建议,我欢迎它。

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);

    }


 }

1 个答案:

答案 0 :(得分:2)

让我们专注于导致问题的代码,仅代码。我已经创建了一个最小的示例程序,一个有足够的代码来编译和运行,并且演示了这个问题,但是没有不必要的代码:

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);
        });
    }
}

因此,如果您运行此代码,您将看到4个非常小的JTextField。他们为什么这么小?因为您没有为JTextFields设置columns属性,所以它们默认为列大小为0并显示如下:

enter image description here

因此,如果您可以为JTextField提供一个列属性,以便它们具有一定的宽度,例如,进行此更改,那就更好了:

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();

但这只是显示了一个JTextField,并且也切断了底部:

enter image description here

为什么呢?因为你人为地限制了包含JPanel的大小,主要来自:

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

这包含JPanel只有128像素宽,20像素高,这意味着它甚至不会很好地显示一个JTextField。

一种解决方案是使用布局管理器和JPanel以及JScrollPane的混合来允许添加JPanel的网格,就像这样(试一试!):

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());
    }
}

这将创建一行JPanel,它包含四个JTextField,当按下add JButton时,它们会被添加到JScrollPane中,如下所示:

enter image description here

但我们仍然可以做得更好。为什么不创建一个类来保存一行数据,如下所示:

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

}

然后创建一个带有自定义模型的JTable,以显示此类型的对象,然后在GUI中显示它们。这更清洁,更灵活,可扩展。像这样:

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);
    }
}

看起来像是:

enter image description here