2011-09-28 12 views
5

aquí hay un SSCCE:oscilación BoxLayout problema JComboBox sin utilizar setXXXSize

import java.awt.Color; 
import java.awt.Dimension; 
import javax.swing.Box; 
import javax.swing.BoxLayout; 
import javax.swing.JButton; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 


public class BoxLayoutTest extends JFrame { 

    public BoxLayoutTest(){ 
     JPanel main = new JPanel(); 
     main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS)); 
     main.setBackground(Color.red); 
     this.add(main); 
     JPanel northPanel = new JPanel(); 

     JPanel middle = new JPanel(); 
     middle.setLayout(new BoxLayout(middle, BoxLayout.X_AXIS)); 
     middle.add(new JButton("FOO")); 
     middle.add(Box.createHorizontalGlue()); 

     JPanel aPanel = new JPanel(); 
     aPanel.setBackground(Color.black); 

      JComboBox b = new JComboBox(); 
    //b.setPreferredSize(new Dimension(100,16)); //uncomment this to see the layout I would like to achieve 
    //b.setMaximumSize(new Dimension(100,16)); 
     //middle.add(b); //uncomment this line 

     middle.setBackground(Color.green); 
     northPanel.setBackground(Color.blue); 

     main.add(northPanel); 
     main.add(middle); 
     main.add(Box.createVerticalGlue()); 

     this.setSize(800,600); 
     this.setResizable(true); 
     this.setVisible(true); 
    } 

    public static void main(String[] args) { 
     new BoxLayoutTest(); 
    } 

} 

Estoy tratando de refactorizar algunas clases que escribí hace algún tiempo, cuando yo no sabía que el uso de métodos setXXXSize en los componentes es incorrecto . El uso de un marco de tamaño variable, el resultado que quiero conseguir es la siguiente:

  1. El NorthPanel debe permanecer en la cima y cambiar su tamaño de acuerdo a las modificaciones de tamaño de marco (parece que funciona bien)
  2. El panel verde donde pongo el JButton debería mantener la dimensión máxima del JButton y permanecer justo debajo del panel azul de arriba (esto funciona bien si solo pongo JButtons dentro de ese panel).

El problema surgiría si pongo un JComboBox dentro del panel verde (tratar de comentar la línea en el SSCCE). Supongo que JComboBox no tiene un tamaño máximo especificado, por lo que se extiende con el marco. En la versión incorrecta anterior de mi código, estaba usando métodos setxxxSize en JComboBox para limitar su dimensión (intente descomentar la línea en los métodos setXXXSize para verla).

Mi pregunta es:

  1. ¿Es posible lograr el mismo resultado utilizando BoxLayout sin invocar setXXXSize() métodos?
  2. En caso afirmativo, ¿cómo?
  3. ¿Hay algún otro LayoutManager que pueda usar para obtener ese efecto?

Por favor, me puso en la dirección correcta

Respuesta

9

JComboBox se está portando mal (lo mismo que JTextField) al reportar una altura máxima sin límites: nunca debe mostrar más de una sola línea. Remedio es el mismo: la subclase y devolver una altura razonable

 JComboBox b = new JComboBox() { 

      /** 
      * @inherited <p> 
      */ 
      @Override 
      public Dimension getMaximumSize() { 
       Dimension max = super.getMaximumSize(); 
       max.height = getPreferredSize().height; 
       return max; 
      } 

     }; 

sólo por diversión, aquí está un fragmento usando MigLayout (que es mi favorito personal :-)

// two panels as placeholders 
    JPanel northPanel = new JPanel(); 
    northPanel.setBackground(Color.YELLOW); 
    JPanel southPanel = new JPanel(); 
    southPanel.setBackground(Color.YELLOW); 
    // layout with two content columns 
    LC layoutContraints = new LC().wrapAfter(2) 
      .debug(1000); 
    AC columnContraints = new AC() 
    // first column pref, followed by greedy gap 
      .size("pref").gap("push") 
      // second 
      .size("pref"); 
    // three rows, top/bottom growing, middle pref 
    AC rowContraints = new AC() 
     .grow().gap().size("pref").gap().grow(); 
    MigLayout layout = new MigLayout(layoutContraints, columnContraints, 
      rowContraints); 
    JPanel main = new JPanel(layout); 
    main.setBackground(Color.WHITE); 
    // add top spanning columns and growing 
    main.add(northPanel, "spanx, grow"); 
    main.add(new JButton("FOO")); 

    // well-behaved combo: max height == pref height 
    JComboBox combo = new JComboBox() { 

     @Override 
     public Dimension getMaximumSize() { 
      Dimension max = super.getMaximumSize(); 
      max.height = getPreferredSize().height; 
      return max; 
     } 

    }; 
    // set a prototype to keep it from constantly adjusting 
    combo.setPrototypeDisplayValue("somethingaslongasIwant"); 

    main.add(combo); 
    // add top spanning columns and growing 
    main.add(southPanel, "spanx, grow"); 
+0

gracias por la respuesta. Parece que es un error de Swing, ¿se solucionará? – Heisenbug

+0

@Heisenbug - no sé, pregúntale al equipo de Swing :-) – kleopatra

3

que siempre han visto con el los administradores de diseño en el jdk no son fáciles. Son demasiado simples e inflexibles, o la resolución de la bolsa de red es demasiado problema. En cambio, comencé a usar el diseño de formulario de jgoodies y nunca miré hacia atrás desde ... Mírelo. Es muy simple y fácil de usar. Aquí hay un enlace:

http://www.jgoodies.com/freeware/forms/

asegúrese de ir a través del papel blanco.

Y ahora, también tenemos google proporcionándonos un editor WYSISWG para el formlayout como un complemento para eclipse. Esto simplemente hace la vida mucho más fácil.

http://code.google.com/javadevtools/wbpro/palettes/swing_palette.html