2014-04-02 44 views
2

我試圖建立類似於MigLayout以下佈局四溢:MigLayout跨距部件從細胞

基本上3列:一個按鈕,一個標籤,並用列表中的其他成分之一(跨越2列)和一個文本區域(應與第三列中的其他組件對齊)。訣竅是按鈕列跨越所有的從最後兩個開的行和其分裂成8個(每個按鈕)。不過我最終的按鈕重疊的名單,並與您的調試可以看到按鈕實際上是溢出的細胞。當我將按鈕放入另一個面板然後將其添加到主面板時,仍會發生這種情況。

添加膠水(或其他幾乎不可見的組件)會導致窗口大小調整(我希望底部組件佔用所有額外空間)時在按鈕和底部組件之間出現間隙。

有沒有一些方法來對底部部件推到下面的按鈕,使他們獲得從調整任何額外的空間?

本來貼出的截圖,但我的第一篇文章,所以我沒有代表感謝mKorbel!)

enter image description here

代碼:

import net.miginfocom.swing.MigLayout; 

import javax.swing.*; 
import javax.swing.border.EmptyBorder; 
import java.awt.*; 

public class MigLayoutTest extends JPanel 
{ 
    private MigLayoutTest() 
    { 
     JFrame frame = new JFrame("MigLayout Test"); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     frame.setContentPane(new JScrollPane(getPage())); 
     frame.getContentPane().setMinimumSize(new Dimension(650, 336)); 
     frame.getContentPane().setPreferredSize(new Dimension(890, 562)); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    private JPanel getPage() 
    { 
     JPanel panel = new JPanel(new MigLayout("fill, wrap 3, debug", "[][][grow, fill]")); 
     panel.setBorder(new EmptyBorder(10, 10, 10, 10)); 

     // To add buttons directly to panel uncomment the commented out lines below and comment out each line that references listButtonPanel 
     JPanel listButtonPanel = new JPanel(new MigLayout("ins 0, wrap 1, aligny top")); 
     Dimension btnSize = new Dimension(105, 25); 
     JButton addBtn = new JButton("Add"); 
     addBtn.setPreferredSize(btnSize); 
     listButtonPanel.add(addBtn); 
     // panel.add(addBtn, "spany 4, split 8, flowy"); 

     JButton removeBtn = new JButton("Remove"); 
     removeBtn.setPreferredSize(btnSize); 
     listButtonPanel.add(removeBtn); 
     // panel.add(removeBtn); 

     JButton copyBtn = new JButton("Copy"); 
     copyBtn.setPreferredSize(btnSize); 
     listButtonPanel.add(copyBtn); 
     // panel.add(copyBtn) 

     panel.add(listButtonPanel, "spany 2, aligny top, hmax 100%"); 

     JTextField txtField = new JTextField(); 
     JLabel label = new JLabel("Property 1"); 
     label.setLabelFor(txtField); 
     panel.add(label, "alignx right"); 
     panel.add(txtField); 

     JComboBox comboBox = new JComboBox(new String[] {"cbx itm 1", "cbx itm 2", "cbx itm 3"}); 
     comboBox.setEditable(true); 
     comboBox.setSelectedItem(""); 
     label = new JLabel("ComboBox Property"); 
     label.setLabelFor(comboBox); 
     panel.add(label, "alignx right"); 
     panel.add(comboBox); 

     panel.add(new JLabel("A big JList"), "spanx 2, grow"); 
     panel.add(new JLabel("A big JTextArea")); 

     JList list = new JList(new DefaultListModel()); 
     list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
     list.setVisibleRowCount(-1); 
     String[] names = new String[] {"Stuff to", "fill this", "JList..."}; 
     DefaultListModel model = (DefaultListModel)list.getModel(); 
     for (String name : names) 
      model.addElement(name); 
     JScrollPane scroller = new JScrollPane(list); 
     scroller.setMinimumSize(new Dimension(213, 100)); 
     scroller.setPreferredSize(new Dimension(213, 100)); 
     panel.add(scroller, "spanx 2, grow, pushy"); 

     JTextArea textArea = new JTextArea(); 
     scroller = new JScrollPane(textArea); 
     scroller.setPreferredSize(new Dimension(100, 100)); 
     panel.add(scroller, "grow, pushy"); 

     return panel; 
    } 

    public static void main(String[] args) 
    { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { new MigLayoutTest(); } 
     }); 
    } 
} 
+0

+1,圖片及所有相關代碼 – Thomas

回答

0

托馬斯的回答工作,只要面板具有行的靜態數量,這不幸的是我們的程序沒有。爲了解決這個問題我跟蹤我要去多少行創建,然後動態生成在最後的行限制。 (這有點麻煩,但沒有我想象的那麼糟糕,如果有辦法避免行約束,我會相應地更新代碼)。我還在按鈕面板旁邊的組件和列表和文本框之間使用了一個虛擬行在底部佔據額外的空間,保持一切正確對齊而不調整大小。

import net.miginfocom.swing.MigLayout; 

import javax.swing.*; 
import javax.swing.border.EmptyBorder; 
import java.awt.*; 

public class MigLayoutTest extends JPanel 
{ 
    private MigLayoutTest(boolean addExtraRow1, boolean addExtraRow2) 
    { 
     JFrame frame = new JFrame("MigLayout Test"); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     frame.setContentPane(new JScrollPane(getPage(addExtraRow1, addExtraRow2))); 
     frame.getContentPane().setMinimumSize(new Dimension(650, 336)); 
     frame.getContentPane().setPreferredSize(new Dimension(890, 562)); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    private JPanel getPage(boolean addExtraRow1, boolean addExtraRow2) 
    { 
     // Create buttons panel 
     JPanel listButtonPanel = new JPanel(new MigLayout("ins 0, wrap 1, aligny top")); 
     JButton addBtn = new JButton("Add"); 
     listButtonPanel.add(addBtn, "w 105px, h 25px, sg btns"); 

     JButton removeBtn = new JButton("Remove"); 
     listButtonPanel.add(removeBtn, "sg btns"); 

     JButton copyBtn = new JButton("Copy"); 
     listButtonPanel.add(copyBtn, "sg btns"); 

     // Create other components 
     int rowCount = 1; // make a dummy row at the bottom to push all the components beside the button panel up 

     JTextField txtField = new JTextField(); 
     rowCount++; 

     JComboBox comboBox = new JComboBox(new String[] {"cbx itm 1", "cbx itm 2", "cbx itm 3"}); 
     comboBox.setEditable(true); 
     comboBox.setSelectedItem(""); 
     rowCount++; 

     JCheckBox checkBox = null; 
     if (addExtraRow1) 
     { 
      checkBox = new JCheckBox(); 
      rowCount++; 

     } 

     JTextField optTxtField = null; 
     if (addExtraRow2) 
     { 
      optTxtField = new JTextField(); 
      rowCount++; 
     } 

     rowCount++; 

     JList list = new JList(new DefaultListModel()); 
     list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
     list.setVisibleRowCount(-1); 
     String[] names = new String[] {"Stuff to", "fill this", "JList..."}; 
     DefaultListModel model = (DefaultListModel)list.getModel(); 
     for (String name : names) 
      model.addElement(name); 

     JTextArea textArea = new JTextArea(); 

     // Generate row constraints 
     StringBuilder rowConstraints = new StringBuilder(); 
     for (int i=0; i<rowCount; i++) 
      rowConstraints.append("[]"); 
     rowConstraints.append("[grow, fill]"); 

     // Create main panel and add components 
     JPanel panel = new JPanel(new MigLayout("fill, wrap 3, debug", "[][][grow, fill, align left]", rowConstraints.toString())); 
     panel.setBorder(new EmptyBorder(10, 10, 10, 10)); 

     panel.add(listButtonPanel, "spany " + --rowCount + ", aligny top, hmax 100%"); // decrement rowCount because the buttons should be above the bottom components' labels 

     addComponent(panel, new JLabel("Property 1"), txtField); 
     addComponent(panel, new JLabel("ComboBox Property"), comboBox); 
     if (checkBox != null) 
      addComponent(panel, new JLabel("Extra comp 1"), checkBox); 
     if (optTxtField != null) 
      addComponent(panel, new JLabel("Extra comp 2"), optTxtField); 

     panel.add(new JLabel("A big JList"), "skip 3, spanx 2, grow"); // skip the dummy row before adding this 
     panel.add(new JLabel("A big JTextArea")); 

     panel.add(new JScrollPane(list), "hmin 100px, spanx 2, grow"); 
     panel.add(new JScrollPane(textArea), "hmin 100px, grow"); 

     return panel; 
    } 

    private void addComponent(JPanel panel, JLabel label, Component component) 
    { 
     label.setLabelFor(component); 
     panel.add(label, "align right"); 
     panel.add(component); 
    } 

    public static void main(final String[] args) 
    { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { new MigLayoutTest(args.length > 1, args.length == 2); } 
     }); 
    } 
} 
0

我認爲,「拆分並跨越單元格按鈕面板「與推混合的東西了。我很抱歉,但我不知道爲什麼。一些可選的提示:

  • 我喜歡單獨聲明,初始化和添加所有組件。我認爲它更易讀易維護。
  • 避免硬編碼的setSize功能。我不記得我得到了我想要的東西。我喜歡MigLayout的sizegroup限制。
  • 不要使用變量兩個對象實例(例如滾輪)。它通常會導致使用對象引用的錯誤。

這裏是另一個可能的解決方案(我希望這仍然滿足您的要求):

private JPanel getPage() { 
    JPanel panel = new JPanel(new MigLayout("wrap 3, debug", "[][][grow, fill]", "[][][][grow, fill]")); 
    panel.setBorder(new EmptyBorder(10, 10, 10, 10)); 

    JButton addBtn, removeBtn, copyBtn; 
    JTextField txtField; 
    JTextArea textArea; 
    JComboBox<String> comboBox; 
    JList<String> list; 
    JLabel property, comboboxLabel, listLabel, textAreaLabel; 
    JScrollPane listScroller, textFieldScroller; 

    addBtn = new JButton("Add"); 
    removeBtn = new JButton("Remove"); 
    copyBtn = new JButton("Copy"); 
    txtField = new JTextField(); 
    textArea = new JTextArea(); 
    property = new JLabel("Property 1"); 
    listLabel = new JLabel("A big JList"); 
    textAreaLabel = new JLabel("A big JTextArea"); 
    comboboxLabel = new JLabel("ComboBox Property"); 


    comboBox = new JComboBox<String>(new String[] { "cbx itm 1", "cbx itm 2", "cbx itm 3" }); 
    comboBox.setEditable(true); 
    comboBox.setSelectedItem(""); 

    list = new JList<String>(); 
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
    list.setVisibleRowCount(-1); 

    String[] names = new String[] { "Stuff to", "fill this", "JList..." }; 
    DefaultListModel<String> model = new DefaultListModel<String>(); 
    for (String name : names) { 
     model.addElement(name); 
    } 
    list.setModel(model); 


    listScroller = new JScrollPane(list); 
    textFieldScroller = new JScrollPane(textArea); 

    property.setLabelFor(txtField); 
    comboboxLabel.setLabelFor(comboBox); 
    textAreaLabel.setLabelFor(textArea); 
    listLabel.setLabelFor(list); 


    panel.add(addBtn, "split 3, flowy, spany 2, sizegroup buttons"); 
    panel.add(removeBtn, "sizegroup buttons"); 
    panel.add(copyBtn, "sizegroup buttons"); 

    panel.add(property, "al right top, sgy components"); 
    panel.add(txtField, "al right top, sgy components"); 
    panel.add(comboboxLabel, "al right top, sgy components"); 
    panel.add(comboBox, "al right top, sgy components"); 

    panel.add(listLabel, "spanx 2, sgy components"); 
    panel.add(textAreaLabel, "sgy components"); 
    panel.add(listScroller, "spanx 2, grow"); 
    panel.add(textFieldScroller, ""); 

    return panel; 
} 
+0

非常感謝。我不認爲拆分必然與它有關,因爲當我將按鈕放在它們自己的面板中時,只需使用spany,我就可以得到相同的結果(請參閱getPage方法中的最佳評論)。還有避免行限制的可能性嗎?我們程序中的面板具有動態數量的組件(textfield和combobox是這些佔位符),我們可以有超過15行使行約束有點笨拙。 –

+0

當然:將行和/或列限制保留爲空,並在將組件添加到面板時使用組件限制。不過,這是更多的代碼。 – Thomas

+0

那麼,我可以在組件約束中使用什麼來替換最後一行約束中的填充?我使用的是頑皮的,但這是什麼原因造成的問題... –