Swing GroupLayout: cambiar el tamaño y limitar el tamaño de los componentes
Lo estoy usando GroupLayout
para administrar componentes en algunos formularios de entrada de datos generados dinámicamente. El diseño es más o menos así:
*-----------------------------------------------*
| label A | field A |
| label B | field B |
| label C | field C |
*-----------------------------------------------*
Estoy usando 2 grupos paralelos para el diseño horizontal y un único grupo secuencial para el diseño vertical. En su mayor parte, todo funciona bien.
Quiero limitar el ancho máximo de las etiquetas (que son solo instancias de JLabel
) a 1/3 del ancho del elemento principal JFrame
. Si JFrame
tuviera un tamaño fijo, esto sería trivial, pero tengo que lidiar con el cambio de tamaño.
Estoy recogiendo ComponentListener.componentResized()
eventos de JFrame
pero estoy un poco atascado en qué hacer una vez que recibo un evento de este tipo.
Probé este enfoque sin suerte:
public void componentResized(ComponentEvent e) {
int maxW = parentFrame.getWidth() / 3;
for (JLabel l : labels) {
l.setMaximumSize( // have also tried setSize() and setPreferredSize()
new Dimension(
Math.min(l.getSize().width, maxW),
l.getMaximumSize().height));
}
groupLayout.invalidateLayout(getContentSpace());
}
¿Alguien puede sugerir una forma de limitar el ancho de las etiquetas que funcione?
Probablemente podría reconstruir el diseño desde cero cada vez, pero creo que debería haber una manera más sencilla.
En este ejemplo, GroupLayout
puede confiar simplemente en el tamaño preferido de la etiqueta, sin tener que recurrir a ningún setXXXSize()
método. En este enfoque,
- El espacio para las etiquetas siempre da cabida a la etiqueta más grande.
- Los campos de texto se pueden cambiar de tamaño de forma útil.
- El resultado es correcto en todas las plataformas y fuentes.
- "No es necesario especificar nada para la mayoría de los componentes... porque los componentes mismos tienen el comportamiento de cambio de tamaño deseado de forma predeterminada".— Cómo utilizar GroupLayout: tamaño y capacidad de cambio de componente
El uso de GroupLayout.Alignment.TRAILING
para justificar a la derecha las etiquetas es una preferencia personal y agregué un segundo panel para mostrar cómo funciona anidado en otro diseño.
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
/** @see http://stackoverflow.com/questions/8492065 */
public class GroupPanel extends JPanel {
private JLabel label1 = new JLabel("Primary:");
private JTextField field1 = new JTextField(16);
private JLabel label2 = new JLabel("Secondary:");
private JTextField field2 = new JTextField(16);
private JLabel label3 = new JLabel("Tertiary:");
private JTextField field3 = new JTextField(16);
public GroupPanel(int n) {
this.setBorder(BorderFactory.createTitledBorder("Panel " + n));
GroupLayout layout = new GroupLayout(this);
this.setLayout(layout);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
layout.setHorizontalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING)
.addComponent(label1)
.addComponent(label2)
.addComponent(label3))
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(field1)
.addComponent(field2)
.addComponent(field3))
);
layout.setVerticalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(label1)
.addComponent(field1))
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(label2)
.addComponent(field2))
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(label3)
.addComponent(field3))
);
}
private static void display() {
JFrame f = new JFrame("GroupPanel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new BoxLayout(f.getContentPane(), BoxLayout.Y_AXIS));
f.add(new GroupPanel(1));
f.add(new GroupPanel(2));
f.add(Box.createVerticalGlue());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
display();
}
});
}
}