Tuve una tarea de Java hace aproximadamente un mes, que se trataba de construir una GUI. Usé GroupLayout para administrar la posición de los componentes. Me encontré con un problema en el que si pongo una cadena de texto muy larga en un JTextField y cambio el tamaño de la ventana exterior, el campo de texto de repente "estalla".
Solucioné el problema con GridBagLayout, pero quería volver al problema original con la esperanza de comprender mejor GroupLayout.
Aquí hay un SSCCE que demuestra este problema. (Traté de minimizarlo tanto como pude, me disculpo si mi ejemplo es demasiado largo).
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); } }
Cuando copio y pego este texto: Let me send you to space 🚀Space travel ASMR Roleplay 🚀(Eng)(Kor) | Roleplay, Storytime, Whitenoise
en uno de los campos de texto y cambia el tamaño de la ventana exterior, el campo de texto "explota".
Establecí el tamaño máximo de los campos de texto en sus tamaños preferidos en createComponents()
, por lo que no entiendo por qué el tamaño del campo de texto excede su tamaño máximo cuando cambio el tamaño de la ventana.
¿Alguien puede explicar por qué tengo este comportamiento extraño?
EDITAR: he anulado el método paint()
para ver cómo cambia el ancho del tamaño del campo de texto.
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); }
Salida antes de cambiar el tamaño
min: 5 pre: 224 max: 224
Salida después de cambiar el tamaño
min: 569 pre: 224 max: 224
Como señaló @matt en los comentarios, esto parece suceder porque el tamaño mínimo se vuelve muy grande. Más notablemente, el tamaño mínimo crece más que el tamaño preferido y el tamaño máximo, lo cual es muy inesperado.
Editar: el comportamiento del tamaño mínimo, que crece después de un cambio de tamaño y se vuelve más grande que el tamaño máximo, parece un error.
Establecer el tamaño mínimo explícitamente es una solución:
.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))
Esto establece el tamaño mínimo y máximo del componente al tamaño predeterminado como se explica en la documentación :
Para hacer que un componente tenga un tamaño fijo (suprimir el cambio de tamaño): group.addComponent(component, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
Puede lograr el mismo comportamiento configurando los tamaños mínimo y máximo:
text1.setMinimumSize(text1.getPreferredSize()); text1.setMaximumSize(text1.getPreferredSize());