2014-02-09 60 views
0

我想用擺動佈局從窗口的當前大小計算出的控件之上留下一個間隙。它基本上可以工作,除非控件只在窗口水平調整大小時才移動 - 如果我垂直調整大小,它會保持原來的位置 - 然後水平調整1個像素的大小,它將捕捉到正確的位置。任何人都可以解釋爲什麼調整大小會被忽略,當我只是垂直調整大小?擺動佈局忽略水平調整大小

我已經證明了componentResized()仍然在垂直調整大小上調用,並且contentPane.getWidth()和contentPane.getHeight()仍然會給出正確的值。所以Dimension的大小設置正確,只是被忽略。它就像我需要打電話到contentPane.payAttentionToUpdatesSizesOfYourComponents(),但我找不到任何這樣做的方法。 contentPane.invalidate()不起作用。

也注意到如果我去掉BorderLayout,並在contentPane中直接設置BoxLayout,那麼它就像我想要的那樣工作。然而,對於這個小例子來說,這很好,我有這個問題的真正的窗口在JPanel中設置了一個位於NORTH的JPanel,上面有一個間隙,另一個JPanel中的一些組件位於SOUTH,間距在下面,BorderLayout是唯一的我可以讓這些位置正確定位,這樣我就不能將其去掉。

任何意見或建議將受到歡迎!

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.event.ComponentAdapter; 
import java.awt.event.ComponentEvent; 

import javax.swing.Box.Filler; 
import javax.swing.BoxLayout; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.WindowConstants; 

public final class ResizeOnlyWorksHorizontally 
{ 
    public static final void main (final String [] args) 
    { 
     final JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation (WindowConstants.EXIT_ON_CLOSE); 

     final JPanel contentPane = new JPanel(); 
     frame.setContentPane (contentPane); 

     contentPane.setLayout (new BorderLayout()); 

     final JPanel top = new JPanel(); 
     top.setLayout (new BoxLayout (top, BoxLayout.Y_AXIS)); 
     contentPane.add (top, BorderLayout.NORTH); 

     // Put a space, then a label below it 
     final Dimension startSpace = new Dimension (0, 0); 
     final Filler filler = new Filler (startSpace, startSpace, startSpace); 
     top.add (filler); 

     top.add (new JLabel ("Text")); 

     contentPane.addComponentListener (new ComponentAdapter() 
     { 
      @Override 
      public final void componentResized (final ComponentEvent e) 
      { 
       // Just any calc based on contentPane width and height to demo problem 
       final int calc = (contentPane.getWidth() + contentPane.getHeight())/2; 

       // Alter the size of the space above the label 
       final Dimension newSpace = new Dimension (0, calc); 
       filler.setMinimumSize (newSpace); 
       filler.setPreferredSize (newSpace); 
       filler.setMaximumSize (newSpace); 
      } 
     }); 

     frame.pack(); 
     frame.setVisible (true); 
    } 
} 

回答

1

要回答你的問題,你需要的大小變化後,必須確保佈局管理器被調用執行以下操作:

filler.revalidate(); 

當然,這是不是一個很好的解決方案,爲您的整個方法問題是錯誤的。你不應該手動計算這樣的組件的大小。這是佈局經理的工作。所以你需要重新思考你的佈局狀態。不要忘記你可以嵌套不同的佈局管理器。

例如,如果您需要在框架中改變空隙,那麼您應該使用BoxLayout,並且可以在開始和結束時添加「膠水」。或者,也許你可以使用GridBagLayout,因爲你可以根據可用空間控制組件的調整方式。

閱讀有關Layout Managers的Swing教程以獲取更多信息。

+0

非常感謝快速回復推 - 的filler.revalidate()的作品,我想我缺少的是,雖然我改變約束的填料,我需要'捅',迫使大小生效,而不是它的容器。 – nigelg

0

它不會讓我在你的答案camickr下放置足夠長的評論:(我想補充一點,發佈後我還發現這個,調整BorderLayouts類似但不完全相同的問題,他們描述了類似的情況NORTH/SOUTH定位控件不注意垂直尺寸 - Java Swing BorderLayout resize difficulties

我試過基於對GridBagLayout的回覆,並且在經過一點努力後纔開始工作。基本上它的1x5網格佈局(空格I強制調整大小,控件,粘貼,更多控件,空間I強制調整大小),並且這個工作。

您不應該手動計算這些組件的大小。

我手動設置的大小的唯一的事情是控制之下+以上的差距,所有的控件本身我讓佈局管理器處理。這些間隙的大小必須與框架上的背景圖像相匹配,而框架的大小與幀的大小保持不變,但保留寬高比,因此該邊框的寬度不是佈局管理器可以計算出的值,「calc」上面我SSCCE位是:

final int edge = Math.min (contentPane.getWidth()/4, contentPane.getHeight()/3); 
final int imgHeight = edge * 3; 
final int borderSize = (contentPane.getHeight() - imgHeight)/2; 

因此,如果用戶調整窗口大小要寬,有黑色邊框左側的圖像+右,和borderSize = 0。如果用戶調整窗口大小要高,圖像下方+上方有黑色邊框,我希望控件避免進入,因此它們總是坐在背景圖像中。

但是非常感謝在正確的方向:)