2015-11-25 121 views
2

我試圖使JPanel(「父面板」)的內容從頂部向底部添加,並有寬度每個組件的高度與父面板的寬度相匹配,同時每個組件的高度都包含內容。內容將被動態生成。JPanel與兒童匹配的父寬度和包裝的高度

這是想什麼我它看起來像:

enter image description here

這已經很容易在Android中的事。我已經看過Swing LayoutManagers,但他們似乎都不是一個明顯的選擇。我試過使用Boxlayout(垂直),除了沒有填充父面板寬度的面板(這使得它看起來非常糟糕)之外,它的工作原理。

感謝您的任何建議!

編輯:

由於camickr的答案,我想它了。如果將來有助於任何人,我已經提供了我的代碼和屏幕截圖。

該解決的問題中的代碼:

(注爲GridBagConstraints的使用的GridBagLayout,BorderLayout的和參數)

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.util.Random; 

import javax.swing.BorderFactory; 
import javax.swing.BoxLayout; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 

public class Test extends JFrame{ 

    private final Color darkGreen = Color.decode("#388E3C"); 
    private final Color green = Color.decode("#4CAF50"); 
    private final Color lightGreen = Color.decode("#C8E6C9"); 

    public static void main(String[] args){ 
     Test test = new Test(); 
     test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    } 

    int noOfTitles = 4; 
    int noOfSubTitles = 3; 
    Random random = new Random(); 

    public Test(){ 


     JPanel parentPanel = new JPanel(); 
     this.setSize(new Dimension(300,800)); 
     this.setContentPane(parentPanel); 
     parentPanel.setBackground(Color.white); 

     //Set layout of parent panel to Gridlayout 
     parentPanel.setLayout(new GridBagLayout()); 

     //Panel for our titles 
     JPanel titlesPanel = new JPanel(); 
     titlesPanel.setLayout(new BoxLayout(titlesPanel, BoxLayout.Y_AXIS)); 

     for(int i = 0;i<noOfTitles;i++){ 
      //Panel for the subtitles of each title 
      JPanel subTitlesPanel = new JPanel(); 
      subTitlesPanel.setLayout(new BoxLayout(subTitlesPanel, BoxLayout.Y_AXIS)); 

      for(int j = 0;j<noOfSubTitles;j++){ 
       //Get a panel with a title header, a collapse/uncollapse button and some sample content 
       subTitlesPanel.add(getCollapsiblePanel(getSampleContent(),"Subtitle")); 
       subTitlesPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); 
      } 
      //Get a panel with a title header, a collapse/uncollapse button and the subtitles as content 
      titlesPanel.add(getCollapsiblePanel(subTitlesPanel,"Title")); 
     } 

     //The constraints for the 
     GridBagConstraints constraints = new GridBagConstraints(); 
     constraints.anchor = GridBagConstraints.PAGE_START; 
     constraints.fill = GridBagConstraints.HORIZONTAL; //Fill the panels horizontally. A weightx is needed for this to work. 
     constraints.gridx = 1; 
     constraints.gridy = 0; 
     constraints.weightx = 1; //Actually makes it fill 
     parentPanel.add(titlesPanel,constraints); 

     //To actually bump the rest of the other stuff to the top, 
     //we need something below with a weighty > 0 
     constraints.gridy = 1; 
     constraints.weighty = 1; 
     constraints.anchor = GridBagConstraints.PAGE_END; 
     parentPanel.add(new JLabel(""),constraints); 

     this.setVisible(true); 
    } 

    /* 
    * Gets a title for the supplied content-panel. 
    * The title includes the titleText and a button for collapsing/uncollapsing the content. 
    */ 
    private JPanel getCollapsiblePanel(JPanel content,String titleText){ 
     JPanel titlePanel = new JPanel(); //Top container for the title 
     JPanel title = new JPanel();  //collapse/uncollapse button and title text 

     title.setLayout(new BoxLayout(title,BoxLayout.X_AXIS)); 
     title.add(getToggleVisibilityIcon(content)); 
     title.add(new JLabel(" "+titleText)); 

     //A border layout is needed here for the fill of the parent panel to work 
     // (I tried with the box layout but it didn't work) 
     titlePanel.setLayout(new BorderLayout()); 
     titlePanel.add(title,BorderLayout.PAGE_START); 
     titlePanel.add(content,BorderLayout.CENTER); 

     //Vanity 
     title.setBackground(green); 
     title.setBorder(BorderFactory.createEmptyBorder(1,1,2,1)); 

     return titlePanel; 
    } 

    /* 
    * Not important, just generates a panel with some "sample" strings. 
    */ 
    private JPanel getSampleContent(){ 
     JPanel content = new JPanel(); 
     content.setLayout(new BoxLayout(content,BoxLayout.Y_AXIS)); 
     for(int i = 0; i<1+random.nextInt(3); i++){ 
      String sampleContent = ""; 
      for(int j = 0;j<1 + random.nextInt(5);j++){ 
       sampleContent += "sample "; 
      } 
      JLabel sample = new JLabel(sampleContent); 
      sample.setForeground(Color.decode("#111111")); 
      content.add(sample); 
     } 
     content.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); 
     content.setBackground(lightGreen); 
     return content; 
    } 

    /* 
    * Method that returns a JLabel that will toggle the visibility of the 
    * supplied content panel upon clicking. 
    */ 
    private JLabel getToggleVisibilityIcon(JPanel content){ 
     JLabel icon = new JLabel(" V "); 
     icon.setBackground(green); 
     icon.setBorder(BorderFactory.createLineBorder(darkGreen,2)); 
     icon.setOpaque(true); 
     icon.addMouseListener(new MouseListener(){ 
      private JPanel content; 
      private JLabel icon; 
      MouseListener init(JPanel content,JLabel icon){ 
       this.content = content; 
       this.icon = icon; 
       return this; 
      } 
      @Override 
      public void mouseClicked(MouseEvent e) { 
       if(content.isVisible()){ 
        content.setVisible(false); 
        icon.setText(" > "); 
       }else{ 
        content.setVisible(true); 
        icon.setText(" V "); 
       } 
      } 

      @Override 
      public void mousePressed(MouseEvent e) {} 
      @Override 
      public void mouseReleased(MouseEvent e) {} 
      @Override 
      public void mouseEntered(MouseEvent e) {} 
      @Override 
      public void mouseExited(MouseEvent e) {} 
     }.init(content,icon)); 
     return icon; 
    } 
} 

運行的應用程序的屏幕截圖:

enter image description here

+0

參見'org.netbeans.swing.outline.Outline',看到[這裏](HTTP:/ /stackoverflow.com/a/15150756/230513)和[there](http://stackoverflow.com/search?tab=votes&q=user%3a230513%20org.netbeans.swing.outline.Outline)。 – trashgod

回答

1

不是很理解你的問題。您通常沒有文字,按鈕和組合框隨機包裝。通常面板具有佈局,所以組件在邏輯上組織。那就是你不想要一個帶有「First Name」文本的標籤,隨後是一個隨機包裝到下一行的文本字段。

它在我看來像你有一個「詳細面板」,你隱藏或顯示?

那麼你可以使用BorderLayout實現這一點。所以隱藏/顯示按鈕將被放置在BorderLayout.PAGE_START中。然後細節面板將在BorderLayout.CENTER中。然後根據需要設置詳細信息面板的可見性。

然後頂級容器可能是GridBagLayout。您可以使用約束來讓每行填充單元格的寬度。每個兒童小組可以使用Border在左側稍微縮進。

閱讀Swing tutorial。上有幾個部分:

  1. 如何使用的GridBagLayout和
  2. 如何使用邊框