2012-11-06 29 views
2

總之,我想用搖擺來實現這一佈局:文字樣的JPanel包裝

enter image description here

注意兩個主要目標:

  • JPanels表現爲文字,他們被包裝爲寬度爲的窗口, 並且在空間不足的情況下,它們被包裝到 JPanels的下一個「行」中。

  • 沒有水平scorll,但垂直滾動目前 訪問查看窗口中的所有可能的元素。

尼克Rippe提供了一個幾乎完成了解決方案below,可以看出here與我的更新更隨機的最裏面textarea的字符串和左aligment獨立的Java程序。

最後一步是修復各行文字區域的頂部對準的cPanel:

((WrapLayout)getLayout()).setAlignOnBaseline(true);

完整的解決方案:

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.border.Border; 

public class APanel extends JScrollPane { 

    int width = 0; 

    public static String getRandomMultilineText() { 
     String filler = ""; 
     int words = (int) (Math.random() * 7) + 1; 
     for (int w = 0 ; w < words ; w++) { 
      int lettersInWord = (int) (Math.random() * 12) + 1; 
      for (int l = 0 ; l < lettersInWord ; l++) { 
       filler += "a"; 
      } 
      filler += "\n"; 
     } 
     return filler.trim(); 
    } 

    public APanel() { 
     super(); 

     setAlignmentX(LEFT_ALIGNMENT); 
     setAlignmentY(TOP_ALIGNMENT); 

     final Box B = Box.createVerticalBox(); 
     B.setAlignmentX(LEFT_ALIGNMENT); 
     B.setAlignmentY(TOP_ALIGNMENT); 

     for (int i = 0 ; i < 4 ; i++) { 
      B.add(new CPanel() { 


       //Important!!! Make sure the width always fits the screen 
       public Dimension getPreferredSize() { 


        Dimension result = super.getPreferredSize(); 
        result.width = width - 20; // 20 is for the scroll bar width 
        return result; 
       } 
      }); 
     } 

     setViewportView(B); 

     //Important!!! Need to invalidate the Scroll pane, othewise it 
     //doesn't try to lay out when the container is shrunk 
     addComponentListener(new ComponentAdapter() { 
      public void componentResized(ComponentEvent ce) { 
       width = getWidth(); 
       B.invalidate(); 
      } 
     }); 
    } 

    // nothing really very special in this class - mostly here for demonstration 
    public static class CPanel extends JPanel { 

     public CPanel() { 
      super(new WrapLayout(WrapLayout.LEFT)); 
      ((WrapLayout)getLayout()).setAlignOnBaseline(true); 


      setOpaque(true); 
      setBackground(Color.gray); 
      setAlignmentY(TOP_ALIGNMENT); 
      setAlignmentX(LEFT_ALIGNMENT); 


      int wordGroups = (int) (Math.random() * 14) + 7; 

      //Adding test data (TextAreas) 
      for (int i = 0 ; i < wordGroups ; i++) { 

       JTextArea ta = new JTextArea(getRandomMultilineText()); 
       ta.setAlignmentY(TOP_ALIGNMENT); 
       ta.setAlignmentX(LEFT_ALIGNMENT); 
       add(ta); 
      } 
      Border bx = BorderFactory.createTitledBorder("Lovely container"); 

      setBorder(bx); 
     } 
    } 

    public static void main(String[] args) { 
     final JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(new APanel()); 
     frame.pack(); 
     frame.setSize(400 , 300); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 
} 
+0

問題不在於面板D,問題在於'JScrollPane'(更準確地說,是'JViewPort')。基本上,它要麼直接使用,要麼就像'BorderLayout'一樣工作,導致窗格D的大小適合可用空間。 – MadProgrammer

+1

請張貼一些代碼來展示如何創建B-Panel的佈局。 – Flawyte

+0

我想了解最內層的JPanel從文本中獲得它們的大小。 –

回答

1

你的問題是你對你的首選大小的計算面板C.此首選大小需要同時覆蓋(寬度)幷包含默認高度。

我已經把一個演示,所以你可以看到這是如何做到:

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

public class APanel extends JScrollPane { 

    int width = 0; 

    public APanel(){ 
     super();   

     final Box B = Box.createVerticalBox(); 

     for(int i = 0; i < 4; i++){ 
      B.add(new CPanel(){ 

       //Important!!! Make sure the width always fits the screen 
       public Dimension getPreferredSize(){ 
        Dimension result = super.getPreferredSize(); 
        result.width = width - 20; // 20 is for the scroll bar width 
        return result; 
       } 

      }); 
     } 

     setViewportView(B); 

     //Important!!! Need to invalidate the Scroll pane, othewise it 
     //doesn't try to lay out when the container is shrunk 
     addComponentListener(new ComponentAdapter(){ 
      public void componentResized(ComponentEvent ce){ 
       width = getWidth(); 
       B.invalidate(); 
      } 
     }); 
    } 

    // nothing really very special in this class - mostly here for demonstration 
    public static class CPanel extends JPanel{ 

     //Test Data - not necessary 
     static StringBuffer fillerString; 
     static { 
      fillerString = new StringBuffer(); 
      int i = 0; 
      for(char c = '0'; c < 'z'; c++){ 
       fillerString.append(c); 
       if(i++ %10 == 0){ 
        fillerString.append('\n'); 
       } 
      } 
     } 

     public CPanel(){ 
      super(new WrapLayout()); 
      setOpaque(true); 
      setBackground(Color.gray); 

      //Adding test data (TextAreas) 
      for(int i = 0; i < 9; i++){ 
       JTextArea ta = new JTextArea(fillerString.toString()); 
       ta.setAlignmentX(LEFT_ALIGNMENT); 
       add(ta); 
      } 

      setBorder(BorderFactory.createTitledBorder("Lovely container")); 
     } 
    } 

    public static void main(String[] args){ 
     final JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(new APanel()); 
     frame.pack(); 
     frame.setSize(400, 300); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

} 
+0

幾乎完成。用代碼將textareas對齊到最頂端(左對齊確定)是我無法實現的最後一件事。更新後的代碼中包含更多不同的textarea內容:[Pastebin code](http://pastebin.com/MmGdf9nG) –

+0

CPanel top aligment fix:'((WrapLayout)getLayout())。setAlignOnBaseline(true);' –

+0

Good find - I我敢肯定不是WrapLayout的專家(我下載它只是爲了你的問題)。本來會早日回到你身上的,但剛從一些壞的塔科約翰斯(真實的故事)中恢復過來。如果您認爲它可以改進解決方案,我可以將您的查找添加到我的示例中。 –

0

定解決方案不起作用完整的JPanel的,這是因爲基線。要將最小的JPanel對齊到頂部,我們必須覆蓋getBaseLine()返回0.這與.setAlignOnBaseline(true);在每行頂部對齊JPanel。