3

I had a Java assignment about a month ago, which was about building a GUI. I used GroupLayout to manage the position of the components. I ran into a problem where if I put a very long string of text into a JTextField and resize the outer window, the textfield suddenly "bursts".

I fixed the issue using GridBagLayout, but I wanted to come back to the original problem in hopes of getting a better understanding of GroupLayout.

Here's a SSCCE that demonstrates this problem. (I tried to minimize it as much as I can, I apologize if my example is too long.)

import javax.swing.*;
import java.awt.*;

public class Main extends JFrame {
    JTextField text1;
    JTextField text2;
    JPanel myPanel;

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(() -> new Main());
    }

    public Main() {
        super("Sussy Imposter");

        createComponents();
        setLayout();
        configureSettings();
    }

    public void createComponents() {
        text1 = new JTextField(20);
        text2 = new JTextField(20);
        text1.setMaximumSize(text1.getPreferredSize());
        text2.setMaximumSize(text2.getPreferredSize());

        myPanel = new JPanel();
        myPanel.setBackground(Color.CYAN);
        myPanel.setPreferredSize(new Dimension(100, 100));
    }

    public void setLayout() {
        Container c = getContentPane();
        GroupLayout groupLayout = new GroupLayout(c);
        c.setLayout(groupLayout);

        groupLayout.setAutoCreateGaps(true);
        groupLayout.setAutoCreateContainerGaps(true);
        groupLayout.setHorizontalGroup(
            groupLayout.createSequentialGroup()
            .addComponent(myPanel)
            .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addComponent(text1)
                .addComponent(text2))
        );
        groupLayout.setVerticalGroup(
            groupLayout.createParallelGroup()
                .addComponent(myPanel)
                .addGroup(groupLayout.createSequentialGroup()
                    .addComponent(text1)
                    .addComponent(text2))
        );
    }

    public void configureSettings() {
        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);
    }
}

Result of the SSCCE

When I copy-paste this text: Let me send you to space Space travel ASMR Roleplay (Eng)(Kor) | Roleplay, Storytime, Whitenoise into one of the textfields, and resize the outer window, the textfield "bursts".

enter image description here

I've set the maximum size of the textfields to their preferred sizes in createComponents(), so I don't understand why the size of the textfield exceeds its maximum size when I resize the window.

Can anyone explain why I'm getting this odd behavior?

EDIT: I've overrided the paint() method to see how the width of the textfield size change.

public void paint(Graphics g) {
    super.paint(g);
    System.out.printf("min: %d\n", text1.getMinimumSize().width);
    System.out.printf("pre: %d\n", text1.getPreferredSize().width);
    System.out.printf("max: %d\n", text1.getMaximumSize().width);
}

Output before resizing

min: 5
pre: 224
max: 224

Output after resizing

min: 569
pre: 224
max: 224

As @matt pointed out in the comments, this seems to happen because the minimumSize becomes very large. More notably, the minimumSize grows larger than the preferredSize and the maximumSize, which is very unexpected.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Kcits970
  • 640
  • 1
  • 5
  • 23
  • So this appears to happen because the minimumSize gets changed to a really large value. The strangest part about it for me, it only happens when I paste in the text with the emoji's if I just use a bunch of text that extends beyond the edge of the text field it behaves properly. – matt Jan 10 '22 at 15:30
  • That is SO WEIRD! The fact that the minimumSize becomes larger than the maximumSize is such an unexpected behavior – Kcits970 Jan 10 '22 at 22:41
  • 1
    Let me know if you decide that getting that layout is more important than debugging the problems with the group layout. It is easily done with a combination of other layouts, and I neither use nor debug group layout. **BTW:** *"Here's a SSCCE that demonstrates this problem. (I tried to minimize it as much as I can, I apologize if my example is too long.)"* No, it is short and to the point. Nice work! As the author of the SSCCE document, I consider anything under 100 lines of code as qualifying as 'short'. – Andrew Thompson Jan 11 '22 at 00:31
  • @matt _So this appears to happen because the minimumSize gets changed to a really large value_ can you post code that proves it ? – c0der Jan 11 '22 at 08:29
  • 1
    @c0der I've added some more code in my question regarding that, I've overrided the `paint()` method to check the minimum, preferred, and maximum sizes – Kcits970 Jan 11 '22 at 08:34
  • 1
    @c0der I added a component listener in the example posted, and printed the dimensions. – matt Jan 11 '22 at 08:47
  • @matt I see what you mean. Anyway explicitly setting min size works around this bug, as you can see in my answer. – c0der Jan 11 '22 at 14:21

1 Answers1

0

Edit: The behavior of the min size, growing after a resize, and becoming larger than the max size seems like a bug.
Setting the min size explicitly is a workaround it:

.addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
    .addComponent(text1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
    .addComponent(text2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))

This sets the component min and max size to default size as explained in the documentation:

To make a component fixed size (suppress resizing): group.addComponent(component, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)

You can achieve the same behavior by setting the min as well as the max sizes:

text1.setMinimumSize(text1.getPreferredSize());
text1.setMaximumSize(text1.getPreferredSize());
c0der
  • 18,467
  • 6
  • 33
  • 65
  • I'm confused, according to https://docs.oracle.com/javase/tutorial/uiswing/layout/group.html#:~:text=component%20size%20and%20resizability, the doc says `If not specified explicitly, the layout asks the component for its default sizes (by using the component's getMinimumSize(), getPreferredSize() and getMaximumSize() methods).` I've already specified the preferred size and the maximum size for the text fields, so the layout should grab that information and use it. Why does it suddenly work if the minimum size is specified? – Kcits970 Jan 10 '22 at 15:33