2013-07-25 199 views
2

我想使面板具有受约束的最大宽度,但当容器变短时会减小其宽度。GridBagLayout和最小宽度

我使用了GridBagLayout,但当尺寸变得足够短时,它表现得很奇怪。

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 

/** 
* @author Michael Nesterenko 
* 
*/ 
public class SSCE extends JFrame { 

    /** 
    * 
    */ 
    public SSCE() { 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     GridBagLayout gbl = new GridBagLayout(); 
     gbl.columnWidths = new int[] {200, 1}; 
     gbl.columnWeights = new double[] {0, 1}; 
     gbl.rowHeights = new int[] {10}; 
     gbl.rowWeights = new double[] {0}; 
     setLayout(gbl); 

     GridBagConstraints gbc = new GridBagConstraints(); 
     gbc.fill = GridBagConstraints.HORIZONTAL; 

     JPanel sizeRestrictedPanel = new JPanel(); 
     sizeRestrictedPanel.setBackground(Color.BLUE); 
     sizeRestrictedPanel.setMinimumSize(new Dimension(50, 50)); 
     sizeRestrictedPanel.setMaximumSize(new Dimension(300, 50)); 
     sizeRestrictedPanel.setPreferredSize(new Dimension(300, 50)); 
     add(sizeRestrictedPanel, gbc); 

     JPanel dummy = new JPanel(); 
     dummy.setBackground(Color.RED); 
     add(dummy, gbc); 

     setPreferredSize(new Dimension(600, 200)); 
     pack(); 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     new SSCE().setVisible(true); 
    } 

} 

当帧宽度变得足够短蓝色面板瞬间调整大小,但是我希望它平滑地调整窗口大小调整大小。

+1

使用'setXxXSize()'方法也可能是罪魁祸首。如果你可以提供一个你想要得到的结果的小图像,这将有帮助:-) –

+0

@nIcEcOw,当窗口足够大时,我希望蓝色面板有一些限制宽度,但是当窗口是做得更短(所以'蓝色'面板不再适合)'蓝色'面板的宽度等于窗口的宽度并且平滑地调整大小。目前它只是跳到一些较小的价值。 –

+0

请看看这个[回复](http://stackoverflow.com/a/9645548/1057230),看看它是否与你的情况相似。为了确定大小,您可以考虑使用[ComponentListener](http://docs.oracle.com/javase/7/docs/api/java/awt/event/ComponentListener.html)并将其附加到您的'Blue JPanel' –

回答

2

可以定义GridBagConstraints.ipadxGridBagConstraints.ipady约束来设定最低宽度/高度

/** 
* This field specifies the internal padding of the component, how much 
* space to add to the minimum width of the component. The width of 
* the component is at least its minimum width plus 
* <code>ipadx</code> pixels. 
* <p> 
* The default value is <code>0</code>. 
* @serial 
* @see #clone() 
* @see java.awt.GridBagConstraints#ipady 
*/ 
public int ipadx; 

/** 
* This field specifies the internal padding, that is, how much 
* space to add to the minimum height of the component. The height of 
* the component is at least its minimum height plus 
* <code>ipady</code> pixels. 
* <p> 
* The default value is 0. 
* @serial 
* @see #clone() 
* @see java.awt.GridBagConstraints#ipadx 
*/ 
public int ipady; 
2

当窗口的宽度是由用户减少,只有红色面板收缩在第一。

该问题的代码示例实际上是以超出打包组件的大小展开的窗口开始的。如果我们删除setPreferredSize(new Dimension(600, 200));行,那么我们会看到下面显示的窗口,而不是带有扩展红色面板的窗口。如果我们将宽度减小到小于这个尺寸,那么我们迫使蓝色面板小于它的首选尺寸,并且“表现奇怪”。这是因为,由于GridBagLayout不再能够兑现蓝色面板的首选尺寸,现在它给每个面板提供相同的空间,并试图遵守其最小尺寸。

enter image description here

我建议没有使用了setPreferredSize使用GridBagLayout的。 您可能希望确定窗口仍然有用所需的最小尺寸,并且不允许用户将尺寸减小到最小值以下。当用户扩展窗口时,某些组件不应该占用比最初分配的空间更多的空间。我们可以使用GridBagConstraints weightx和weighty来代替setMaximumSize

下面的代码显示了两个面板顺利调整大小,并且我添加了一些文本以显示调整后的尺寸。

import java.awt.*; 
import java.awt.event.ComponentAdapter; 
import java.awt.event.ComponentEvent; 
import javax.swing.*; 

/** 
* @author Michael Nesterenko, Leon LaSpina 
* 
*/ 
public class SSCE extends JFrame { 
    JLabel blueDimension, redDimension; 
    JPanel sizeRestrictedPanel, dummyPanel, bottomPanel; 

    public SSCE() { 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JPanel testPanel = new JPanel(); 
     bottomPanel = new JPanel(); 
     setLayout(new BorderLayout()); 
     GridBagLayout gbl = new GridBagLayout(); 
     testPanel.setLayout(gbl); 
     add(testPanel, BorderLayout.CENTER); 
     add(bottomPanel, BorderLayout.SOUTH); 
     GridBagConstraints gbc = new GridBagConstraints(); 
     gbc.fill = GridBagConstraints.HORIZONTAL; 
     gbc.weightx = 0.75; 

     sizeRestrictedPanel = new JPanel(); 
     sizeRestrictedPanel.setBackground(Color.BLUE); 
     sizeRestrictedPanel.setMinimumSize(new Dimension(50, 50)); 
     sizeRestrictedPanel.setMaximumSize(new Dimension(300, 50)); 
     //sizeRestrictedPanel.setPreferredSize(new Dimension(300, 50)); 
     testPanel.add(sizeRestrictedPanel, gbc); 
     dummyPanel = new JPanel(); 
     dummyPanel.setBackground(Color.RED); 
     dummyPanel.setMinimumSize(new Dimension(50, 50)); 
     //dummyPanel.setPreferredSize(new Dimension(50, 50)); 
     gbc.weightx = 0.25; 
     testPanel.add(dummyPanel, gbc); 

     setSize(new Dimension(600, 200)); 
     blueDimension = new JLabel("------"); 
     blueDimension.setForeground(Color.BLUE); 
     redDimension = new JLabel("------"); 
     redDimension.setForeground(Color.RED); 
     bottomPanel.add(blueDimension); 
     bottomPanel.add(new JLabel(" ")); 
     bottomPanel.add(blueDimension); 
     bottomPanel.add(redDimension); 
     this.addComponentListener(new ComponentAdapter() { 
     public void componentResized(ComponentEvent e) { 
      updateDimensionText(); 
     } 
     }); 
    } 

    private void updateDimensionText() { 
     Dimension d1 = sizeRestrictedPanel.getSize(); 
     String s1 = d1.width + "," + d1.height; 
     Dimension d2 = dummyPanel.getSize(); 
     String s2 = d2.width + "," + d2.height; 
     blueDimension.setText(s1); 
     redDimension.setText(s2); 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     SSCE win = new SSCE(); 
     win.setVisible(true); 
     win.updateDimensionText(); 
    } 
}