Java Swing GridBagLayout JTextField添加错误消息后更改大小

时间:2018-09-25 14:48:33

标签: java swing jpanel layout-manager gridbaglayout

一段时间以来,我一直在追捕这个错误,似乎无法弄清楚。我有一个带有标签和文本字段列表的小型GUI。在带有标签+文本字段的行之间,有一个空行,其中包含一个JLabel,以根据需要填充一条错误消息。问题是,当填充此错误消息时,由于某种原因压缩了它们上方的文本字段,并且在尝试了几小时不同的尝试后,我似乎无法查明原因。似乎所有标签/文本区域之间的压缩程度也有所不同。谁能指出这个问题?

我尝试在面板gridbaglayout中为每个元素提供更多空间。这似乎并没有改变最终结果。

如果查看代码,则元素位于“ continuousTransferPanel”上。此外,“ singleTransferPanel”也只有2行存在相同的问题。

No Error Messages

Error Messages

fun loginLoginBtnClicked(view: View): Unit {

        val email = loginEmailTxt.text.toString()
        val password = loginPasswordTxt.text.toString()

        AuthService.loginUser(this, email, password) {success ->
            if (success) {
                AuthService.findUserByEmail(this) {fsuccess ->
                    if (fsuccess) {
                        finish()
                    }
                }
            }

        }
    }

2 个答案:

答案 0 :(得分:2)

这不是一个真正的答案,但是我无法通过尝试MCVE重现您的问题。请注意使用数组和集合(此处为地图)来简化代码:

import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;

@SuppressWarnings("serial")
public class MyPanel extends JPanel {
    public static final String[] LABELS = {"Job Name:", "Source Folder:", "Destination:", "File Regex:"};
    private static final int TF_COLS = 20;
    private static final Font LABEL_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 12);
    private static final Font ERROR_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 8);
    private static final String ERROR_MESSAGE = "Cannot Be Empty";
    private static final Color BACKGROUND = new Color(49, 49, 47);
    private Map<String, JTextField> labelFieldMap = new HashMap<>();
    private Map<String, JLabel> errorLabelMap = new HashMap<>();

    public MyPanel() {
        setLayout(new BorderLayout());
        setBackground(BACKGROUND);

        JPanel labelFieldPanel = new JPanel(new GridBagLayout());
        labelFieldPanel.setOpaque(false);
        for (int i = 0; i < LABELS.length; i++) {
            String text = LABELS[i];
            JLabel label = new JLabel(text);
            JTextField textField = new JTextField(TF_COLS);
            JLabel errorLabel = new JLabel("    ");

            label.setFont(LABEL_FONT);
            label.setForeground(Color.WHITE);
            errorLabel.setFont(ERROR_FONT);
            errorLabel.setForeground(Color.RED);


            labelFieldMap.put(text, textField);
            errorLabelMap.put(text, errorLabel);

            GridBagConstraints gbc = createLabelConstraint(i);
            labelFieldPanel.add(label, gbc);

            gbc = createTextFieldConstraints(i);
            labelFieldPanel.add(textField, gbc);

            gbc = createErrorLabelConstraints(i);
            labelFieldPanel.add(errorLabel, gbc);

            // add blank JLabel at the 0 position
            gbc.gridx = 0;
            labelFieldPanel.add(new JLabel(), gbc); 
        }

        JButton acceptButton = new JButton("Accept");
        acceptButton.setMnemonic(KeyEvent.VK_A);
        acceptButton.addActionListener(e -> {
            for (int i = 0; i < LABELS.length - 1; i++) {
                String text = LABELS[i];
                JTextField textField = labelFieldMap.get(text);
                JLabel errorLabel = errorLabelMap.get(text);
                if (textField.getText().trim().isEmpty()) {
                    errorLabel.setText(ERROR_MESSAGE);
                } else {
                    errorLabel.setText(" ");
                    System.out.println(text + " " + textField.getText());
                }
            }
            System.out.println();
        });
        JPanel btnPanel = new JPanel();
        btnPanel.setOpaque(false);
        btnPanel.add(acceptButton);        

        add(labelFieldPanel, BorderLayout.CENTER);
        add(btnPanel, BorderLayout.PAGE_END);
    }

    private GridBagConstraints createErrorLabelConstraints(int i) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 2 * i + 1;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(0, 5, 0, 5);
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1.0;
        gbc.weighty = 0.0;
        return gbc;
    }

    private GridBagConstraints createTextFieldConstraints(int i) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 2 * i;
        gbc.anchor = GridBagConstraints.EAST;
        gbc.insets = new Insets(5, 0, 0, 5);
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1.0;
        gbc.weighty = 0.0;
        return gbc;
    }

    private GridBagConstraints createLabelConstraint(int i) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 2 * i;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(5, 5, 0, 5);
        gbc.weightx = 0.0;
        gbc.weighty = 0.0;
        return gbc;
    }

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

        JFrame frame = new JFrame("MyPanel");
        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());
    }
}

生成的GUI:

enter image description here enter image description here

答案 1 :(得分:1)

由于问题出在您的JTextField的Border上,并且因为您不能在没有遇到问题的情况下彻底重置默认边框,所以一种解决方案是为JTextField创建CompoundBorder,其外边界是使用与JPanel的背景色,内部边框是JTextField的默认边框。然后,在动作侦听器中,只需创建一个新的复合边框,即使用Color.RED外边框的边框。

因此,在下面的示例中创建我的JTextField时,我还创建了CompoundBorder,为它提供了externalBorder和innerBorder,如下所示:

// create JTextField with TF_COLS int column count value
JTextField textField = new JTextField(TF_COLS);

// get the JTextField's default border and make it our inner border
Border innerBorder = textField.getBorder();

// create an outer LineBorder that uses the JPanel's background color
Border outerBorder = BorderFactory.createLineBorder(BACKGROUND);

// create the compound border with these two borders
CompoundBorder myBorder = BorderFactory.createCompoundBorder(outerBorder, innerBorder);

// and set the JTextField's border with it
textField.setBorder(myBorder);

然后在JButton的ActionListener中,获取JTextField的当前边框,我们的复合边框,并更改外部边框的线条颜色。简单:

// loop through all the JLabel texts
for (int i = 0; i < LABELS.length; i++) {
    String text = LABELS[i];  // get the array item

    // use it to get the JTextField associated with this String
    JTextField textField = labelFieldMap.get(text);
    // same for the error JLabel
    JLabel errorLabel = errorLabelMap.get(text);

    // get our current JTextField's border which is a compound border
    CompoundBorder myBorder = (CompoundBorder) textField.getBorder();

    // the insideBorder, the original JTextField's border, will be unchanged
    Border insideBorder = myBorder.getInsideBorder();

    // if the text field is empty (and not the last jtext field)
    if (i < LABELS.length - 1 && textField.getText().trim().isEmpty()) {
        errorLabel.setText(ERROR_MESSAGE);  // set the error JLabel

        // set txt field's color if we want
        textField.setBackground(ERROR_BG_COLOR); 

        // okToTransfer = false;

        // create a compound border, the outer border now a line border, RED
        Border outsideBorder = BorderFactory.createLineBorder(Color.RED);
        CompoundBorder newBorder = BorderFactory.createCompoundBorder(outsideBorder, insideBorder);

        // set the JTextField's border to this one
        textField.setBorder(newBorder);
    } else {
        // else all OK
        errorLabel.setText(" ");
        textField.setBackground(Color.WHITE);

        // set the JTextField's border back to our original compound border
        Border outsideBorder = BorderFactory.createLineBorder(BACKGROUND);
        CompoundBorder newBorder = BorderFactory.createCompoundBorder(outsideBorder,
                insideBorder);
        textField.setBorder(newBorder);
    }
    System.out.println(text + " " + textField.getText());
}

例如:

import java.awt.*;
import java.awt.Dialog.ModalityType;
import java.awt.event.*;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;

@SuppressWarnings("serial")
public class MyPanel extends JPanel {
    public static final String[] LABELS = { "Job Name:", "Source Folder:", "Destination:",
            "File Regex:" };
    private static final int TF_COLS = 30;
    private static final Font LABEL_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 12);
    private static final Font ERROR_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 8);
    private static final String ERROR_MESSAGE = "Cannot Be Empty";
    private static final Color BACKGROUND = new Color(49, 49, 47);
    private static final String TITLE = "File Transfer Job Editor";
    private static final Color TITLE_COLOR = new Color(243, 112, 33);
    private static final Font TITLE_FONT = new Font("Arial", Font.BOLD, 28);
    private static final Color ERROR_BG_COLOR = new Color(255, 220, 220);
    private Map<String, JTextField> labelFieldMap = new HashMap<>();
    private Map<String, JLabel> errorLabelMap = new HashMap<>();

    public MyPanel() {
        JLabel titleLabel = new JLabel(TITLE, SwingConstants.CENTER);
        titleLabel.setForeground(TITLE_COLOR);
        titleLabel.setFont(TITLE_FONT);

        JPanel titlePanel = new JPanel();
        titlePanel.setOpaque(false);
        titlePanel.add(titleLabel);
        titlePanel.setBorder(BorderFactory.createEtchedBorder());

        JPanel labelFieldPanel = new JPanel(new GridBagLayout());
        labelFieldPanel.setOpaque(false);
        int bGap = 3;
        labelFieldPanel.setBorder(BorderFactory.createEmptyBorder(bGap, bGap, bGap, bGap));

        for (int i = 0; i < LABELS.length; i++) {
            String text = LABELS[i];
            JLabel label = new JLabel(text);
            JTextField textField = new JTextField(TF_COLS);
            JLabel errorLabel = new JLabel("    ");
            Border innerBorder = textField.getBorder();
            Border outerBorder = BorderFactory.createLineBorder(BACKGROUND);
            CompoundBorder myBorder = BorderFactory.createCompoundBorder(outerBorder, innerBorder);
            textField.setBorder(myBorder);

            label.setFont(LABEL_FONT);
            label.setForeground(Color.WHITE);
            errorLabel.setFont(ERROR_FONT);
            errorLabel.setForeground(Color.RED);

            labelFieldMap.put(text, textField);
            errorLabelMap.put(text, errorLabel);

            GridBagConstraints gbc = createLabelConstraint(i);
            labelFieldPanel.add(label, gbc);

            gbc = createTextFieldConstraints(i);
            labelFieldPanel.add(textField, gbc);

            gbc = createErrorLabelConstraints(i);
            labelFieldPanel.add(errorLabel, gbc);

            // add blank JLabel at the 0 position
            gbc.gridx = 0;
            labelFieldPanel.add(new JLabel(), gbc);
        }

        JButton acceptButton = new JButton("Accept");
        acceptButton.setMnemonic(KeyEvent.VK_A);
        acceptButton.addActionListener(e -> {
            boolean okToTransfer = true;
            for (int i = 0; i < LABELS.length; i++) {
                String text = LABELS[i];
                JTextField textField = labelFieldMap.get(text);
                JLabel errorLabel = errorLabelMap.get(text);

                CompoundBorder myBorder = (CompoundBorder) textField.getBorder();
                Border insideBorder = myBorder.getInsideBorder();

                if (i < LABELS.length - 1 && textField.getText().trim().isEmpty()) {
                    errorLabel.setText(ERROR_MESSAGE);
                    textField.setBackground(ERROR_BG_COLOR);
                    okToTransfer = false;
                    Border outsideBorder = BorderFactory.createLineBorder(Color.RED);
                    CompoundBorder newBorder = BorderFactory.createCompoundBorder(outsideBorder, insideBorder);
                    textField.setBorder(newBorder);
                } else {
                    errorLabel.setText(" ");
                    textField.setBackground(Color.WHITE);
                    Border outsideBorder = BorderFactory.createLineBorder(BACKGROUND);
                    CompoundBorder newBorder = BorderFactory.createCompoundBorder(outsideBorder, insideBorder);
                    textField.setBorder(newBorder);
                }
                System.out.println(text + " " + textField.getText());
            }
            System.out.println();
            if (okToTransfer) {
                // TODO: transfer code here
                // Window win = SwingUtilities.getWindowAncestor(MyPanel.this);
                // win.dispose();
            }
        });
        JButton cancelBtn = new JButton("Cancel");
        cancelBtn.setMnemonic(KeyEvent.VK_C);
        cancelBtn.addActionListener(e -> {
            Window win = SwingUtilities.getWindowAncestor(MyPanel.this);
            win.dispose();
        });
        int btnPanelGap = 15;
        JPanel btnPanel = new JPanel(new GridLayout(1, 0, btnPanelGap, 0));
        btnPanel.setBorder(BorderFactory.createEmptyBorder(4, btnPanelGap, 4, btnPanelGap));
        btnPanel.setOpaque(false);
        btnPanel.add(acceptButton);
        btnPanel.add(cancelBtn);

        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        setBackground(BACKGROUND);
        add(titlePanel);
        add(labelFieldPanel);
        add(btnPanel);
    }

    private GridBagConstraints createErrorLabelConstraints(int i) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 2 * i + 1;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(0, 5, 0, 5);
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1.0;
        gbc.weighty = 0.0;
        return gbc;
    }

    private GridBagConstraints createTextFieldConstraints(int i) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 2 * i;
        gbc.anchor = GridBagConstraints.EAST;
        gbc.insets = new Insets(5, 0, 0, 5);
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1.0;
        gbc.weighty = 0.0;
        return gbc;
    }

    private GridBagConstraints createLabelConstraint(int i) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 2 * i;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(5, 5, 0, 5);
        gbc.weightx = 0.0;
        gbc.weighty = 0.0;
        return gbc;
    }

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

        JDialog dialog = new JDialog((JFrame) null, "Job Editor", ModalityType.APPLICATION_MODAL);
        dialog.getContentPane().add(mainPanel);
        dialog.setResizable(false);
        dialog.pack();
        dialog.setLocationRelativeTo(null);
        dialog.setVisible(true);
        System.exit(0);
    }

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