2011-10-31 68 views
0

我有一個自定義的佈局,其中的主要行爲是在JScrollPane寬度變化時增長和縮小子JTextArea。滾動窗格的水平滾動條被禁用,並且文本區域應該展開和收縮,以避免需要horz滾動條。幾個月來,我使用其中一個標準佈局管理器來解決此問題,但現在我需要一些不同的功能。JTextArea不會收縮在佈局管理器內JPanel

發生了什麼事情是,當用戶水平擴展滾動窗格時,將調用佈局管理器layoutContainer方法。它會調整文本區域的大小並正確重排文本。但是,縮小滾動窗格時,不會調用layoutContainer,並且文本區域保持不變。我已經在layoutContainer方法中放置了一些printlns,以便它在工作時顯而易見。

重要的是要注意的問題是JTextArea setColumns被調用。我可以對它進行註釋,並在調整大小時調用layoutContainer。 (當然,那麼文本區域不會調整大小。)我也嘗試使用JTextArea.setSize,結果相同。

在此先感謝您的任何想法。

下面的代碼:

//---------------------------------------------------------------------------- 
//---------------------------------------------------------------------------- 
@SuppressWarnings("serial") 
class XTextArea extends JTextArea 
{ 
    XTextArea (String text) 
    { 
     super (text); 
    } 

    public int getColumnWidth() 
    { 
     return super.getColumnWidth(); 
    } 
} 

//---------------------------------------------------------------------------- 
//---------------------------------------------------------------------------- 
class PackLeftLayout implements LayoutManager 
{ 
    Component viewPort; 
    Component flexWidthComponent; 

    int preferredWidth = 0; 
    int preferredHeight = 0; 

    //---------------------------------------------------------------------------- 
    // viewPort - if null, compute width as sum of component's preferred width; 
    // otherwise width will be the viewPort's width. 
    // flexWidthComponent - if not null, this component width will be sized to right 
    // justify rightmost component. 
    public PackLeftLayout (Component viewPort, Component flexWidthComponent) 
    { 
     super(); 
     this.viewPort = viewPort; 
     this.flexWidthComponent = flexWidthComponent; 
    } 

    //---------------------------------------------------------------------------- 
    public void addLayoutComponent(String name, Component comp) 
    { 
    } 

    //---------------------------------------------------------------------------- 
    public void removeLayoutComponent(Component comp) 
    { 
    } 

    //---------------------------------------------------------------------------- 
    // Calculates the preferred size dimensions for the specified container, given the 
    // components it contains. 
    // parent - the container to be laid out 
    // Components layed out left-to-right with no additional spacing. 
    public Dimension preferredLayoutSize (Container parent) 
    { 
     Insets insets = parent.getInsets(); 
     int width = 0; 
     int height = 0; // will become max of all component's preferred height 

     // calculate sum of fixed width components - skip the flexwidth component 
     width = insets.left + insets.right; 
     for (int i = 0, limit = parent.getComponentCount(); i < limit; i++) 
     { 
      Component c = parent.getComponent(i); 
      if (c.isVisible()) 
      { 
       if (c != flexWidthComponent) 
       { 
        Dimension size = c.getPreferredSize(); 
        if (size.height > height) 
        height = size.height; 
        width += size.width; 
       } 
      } 
     } 

     // determine width of flex width component 
     if (flexWidthComponent != null) 
     { 
      int flexWidth = viewPort.getWidth() - width; 
      if (flexWidth < 1) 
       flexWidth = 1; 

      if (flexWidthComponent instanceof XTextArea) 
      { 
       // some trickery here to get the xtextarea to tell us its preferred height 
       // given a specific width. 
       int colWidth = ((XTextArea)flexWidthComponent).getColumnWidth(); 

       // the following line causes the failure: 
       ((XTextArea)flexWidthComponent).setColumns (flexWidth/colWidth); 

       Dimension taSize = flexWidthComponent.getPreferredSize(); 
       width += taSize.width; 

       if (taSize.height > height) 
        height = taSize.height; 
      } 
      else 
      { 
       Dimension size = flexWidthComponent.getPreferredSize(); 
       width += flexWidth; 
       if (size.height > height) 
        height = size.height; 
      } 
     } 

     preferredWidth = width; // already include insets 
     preferredHeight = height + insets.top + insets.bottom; 

     return new Dimension (preferredWidth, preferredHeight); 
    } 

    //---------------------------------------------------------------------------- 
    // Calculates the minimum size dimensions for the specified container, given the 
    // components it contains. 
    // parent - the component to be laid out 
    public Dimension minimumLayoutSize(Container parent) 
    { 
     return new Dimension (10, 10); //??? 
    } 

    static int k = 0; 
    //---------------------------------------------------------------------------- 
    public void layoutContainer(Container parent) 
    { 
     System.out.println ("layout" + (k++)); 
     Insets insets = parent.getInsets(); 
     int left = insets.left; 

     if (preferredWidth == 0 || preferredHeight == 0) 
      preferredLayoutSize (parent); 

     for (int i = 0, limit = parent.getComponentCount(); i < limit; i++) 
     { 
      Component c = parent.getComponent(i); 
      Dimension size = c.getPreferredSize(); 

      c.setBounds (left, insets.top, size.width, preferredHeight); 

      left += size.width; 
     } 

     // force another layout calc 
     preferredWidth = 0; 
    } 
} 

public class ResizablePane extends JFrame 
{ 

    public static void main(String[] args) 
    { 
     javax.swing.SwingUtilities.invokeLater(
      new Runnable() {public void run() 
      { 
       new ResizablePane(); 
      }}); 
    } 

    ResizablePane() 
    { 
     super ("ResizableDemo"); 

     // put a button and text area into a panel, then into a scroll pane 
     JButton button = new JButton ("button"); 
     XTextArea text = new XTextArea (
      "For three years I ran as fast as I could, trying to live and love and learn at " + 
      "double speed to make up for what Anne-Marie lost. Trying to anesthetize myself " + 
      "from what Id lost. When I decided to read a book a day and write about it, Id " + 
      "finally stopped running away."); 

     text.setLineWrap (true); 
     text.setWrapStyleWord (true); 

     JScrollPane scroll = new JScrollPane(); 
     JPanel panel = new JPanel(); 
     panel.setLayout (new PackLeftLayout(scroll.getViewport(), text)); 
     panel.add (button); 
     panel.add (text); 

     scroll.setHorizontalScrollBarPolicy (ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 
     scroll.setViewportView (panel); 

     getContentPane().add(scroll); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     pack(); 
     setVisible(true); 
    } 
} 
+0

*「最重要的是要注意的是」*這些詞彙中毫無疑問。 –

+0

另請參見['TextPanePerfectSize'](http://stackoverflow.com/questions/3315681/how-can-i-measure-calculate-the-size-a-document-needs-to-render-itself/3318949#3318949 )。 – trashgod

+0

我認爲這可能是文本區域和JScrollPane之間的交互中的某處的錯誤。我發現如果允許水平滾動條,ta會縮小。換句話說,在我的原始代碼中,我有行 setHorizo​​ntalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_​​NEVER); 如果我刪除這條線,ta開始工作...有點。只要滾動條被隱藏,它就會工作。 –

回答

0

這是老問題,但我希望這將是有用的人。 爲我工作:

jScrollPane = new JScrollPane(textArea); jScrollPane.setPreferredSize(jScrollPane.getPreferredSize());

1

的JTextArea不會裏面的JPanel

收縮您需要設置文本區域的最小尺寸:

textArea.SetMinimumSize(new Dimension(100,100)); 

PS。我在我的面板中使用GridLayout只有一個組件。