2012-05-08 24 views
2

我正在使用的用戶界面顯示一個面板,它允許用戶選擇電影並播放。有控件可以播放,暫停等。GridBagLayout - 一行的高度導致下一行的寬度發生變化

佈局看起來像我想要的樣子。該面板使用GridBagLayout。第2行顯示狀態消息的文本區域,第3行顯示帶有按鈕和進度條的面板。

我遇到的問題是,當我在文本區域中有太多文本行時,第3行中的按鈕將環繞。這與外框的高度無關。

行2中的高度影響行3中的寬度。我不理解此行爲。我想知道如果有人能告訴我,我做錯了什麼,我該如何解決?我附上了代碼。

在一個稍微不同的主題上,如果您正在查看代碼,您是否也可以建議一種在最底部組件和最外面的面板之間留出餘量的方法?

非常感謝您的幫助。

問候,
彼得



    private static JButton CreateImageButton(String fileName) { 
     JButton retVal = new JButton("xxx"); 
     return retVal; 
    } 

    public MoviePanel() { 
     this.setLayout(new GridBagLayout()); 
     this.setBackground(Color.WHITE); 

     JButton btnRefresh = CreateImageButton("refresh.png"); 
     GridBagConstraints c = new GridBagConstraints(); 
     c.gridx=0; 
     c.gridy=0; 
     c.fill = GridBagConstraints.NORTH; 
     c.insets.left = 10; c.insets.right = 10; c.insets.top = 10; 
     this.add(btnRefresh, c); 

     JComboBox cbMovieList = new JComboBox(); 
     c = new GridBagConstraints(); 
     c.gridx = 1; 
     c.gridy = 0; 
     c.fill = GridBagConstraints.HORIZONTAL; 
     c.insets.right = 10; c.insets.top = 10; 
     c.weightx = 1.0; 
     this.add(cbMovieList, c); 

     JButton btnAuthorize = new JButton("Get Info"); 
     c = new GridBagConstraints(); 
     c.gridx = 1; 
     c.gridy = 1; 
     c.anchor = GridBagConstraints.WEST; 
     c.insets.top = 10; 
     this.add(btnAuthorize, c); 

     JTextArea txtInfo = new JTextArea(); 
     txtInfo.setFont(new Font("SansSerif", Font.BOLD, 12)); 
     txtInfo.setBackground(Color.cyan); 
     // txtInfo.setText("abc\ndef"); 
     txtInfo.setText("abc\ndef\nghi\njkl\nmno\npqr\nstu\nvwx\nyz"); 
     c = new GridBagConstraints(); 
     c.gridx = 1; 
     c.gridy = 2; 
     c.anchor = GridBagConstraints.NORTHWEST; 
     c.weighty = 1.0; 
     c.insets.top = 10; 

     this.add(txtInfo, c); 

     JPanel controllerOuter = new JPanel(); 
     controllerOuter.setLayout(new BoxLayout(controllerOuter, BoxLayout.Y_AXIS)); 
     controllerOuter.setBorder(BorderFactory.createRaisedBevelBorder()); 

     FlowLayout controllerLayout = new FlowLayout(FlowLayout.CENTER); 
     controllerLayout.setHgap(0); 
     JPanel controller = new JPanel(controllerLayout); 

     controller.setBorder(new EmptyBorder(10, 10, 10, 10)); 

     Dimension dim = new Dimension(60, 40); 
     JButton btnPlay = CreateImageButton("play.png"); 
     btnPlay.setPreferredSize(dim); 

     controller.add(btnPlay); 
     JButton btnPause = CreateImageButton("pause.png"); 
     btnPause.setPreferredSize(dim); 
     controller.add(btnPause); 
     JButton btnStop = CreateImageButton("stop.png"); 
     btnStop.setPreferredSize(dim); 
     controller.add(btnStop); 
     JButton btnForward = CreateImageButton("forward.png"); 
     btnForward.setPreferredSize(dim); 
     controller.add(btnForward); 
     JComboBox cbAspectRatio = new JComboBox(); 
     cbAspectRatio.setPreferredSize(new Dimension(100, 40)); 
     cbAspectRatio.setBorder(new EmptyBorder(0, 10, 0, 0)); 
     controller.add(cbAspectRatio); 

     controllerOuter.add(controller); 

     JProgressBar pbProgress = new JProgressBar(0, 100); 
     pbProgress.setPreferredSize(new Dimension(350, 40)); 
     pbProgress.setBorder(new EmptyBorder(0, 10, 10, 10)); 
     pbProgress.setValue(50); 
     pbProgress.setString("50/100"); 
     pbProgress.setStringPainted(true); 
     pbProgress.setForeground(Color.BLUE); 
     pbProgress.setBorderPainted(true); 
     controllerOuter.add(pbProgress); 


     c = new GridBagConstraints(); 
     c.gridx = 0; 
     c.gridy = 3; 
     c.gridwidth = 2; 
     c.weightx = 1.0; 
     this.add(controllerOuter, c); 
    } 

Here is the image

+0

您是什麼意思_wrap around_?我用TA中的不同文本運行你的代碼幾次,並且按鈕總是在同一個地方。也許編輯你的帖子來添加你看到的問題的屏幕截圖? –

+0

剛剛添加圖片。正如你所看到的,減少了框架的高度後,第五個控制器被包裹起來了。 – Peter

+0

實際上我很困惑,因爲你談論按鈕的包裝,而它是包裝的組合框。我也會很快回復你 –

回答

4

我看到你的代碼幾件事情:

  1. 你強制JButton的preferredSize。如果可能的話,我會刪除它,因爲這通常會給您帶來比解決方案更多的問題。如果你想強制preferredSize,你還應該注意設置最小和最大尺寸,否則你會得到奇怪的行爲,如你正在觀察的
  2. 你使用BoxLayout來顯示控件。雖然這是完全可以接受的,但BoxLayout也依靠最小/最大尺寸來執行您未設置的佈局。
  3. 您使用重疊佈局。這也沒問題,但爲什麼不使用MoviePanel的GridBagLayout?
  4. 通常TextAreas被包裝在JScrollPane中,以防文本太大。你也可以在TextArea上設置LineWrap(true),這樣它就不會在右邊過多。通過設置TextArea上的行/列,您將定義它的preferreSize(以防止它取決於它所包含的文本)。
  5. 在您的GridBagConstraints上,填充屬性只能爲:NONE,VERTICAL,HORIZONTALBOTH(您對其中之一使用了VERTICAL)。此外,不需要重新創建新實例,您可以反覆重複使用同一個GridBagConstraint,當您爲該組件設置約束時,它將由LayoutManager自動克隆。

現在的解決方案,我發現了幾個:

  1. 當您添加contollerOuter,同時指定c.fill = GridBagConstraints.HORIZONTAL;(這是解決你的問題,最簡單的方法)
  2. 當您設置的首選大小JButtons也強制它們的minimumSize達到相同的值。
  3. 僅使用GridBagLayout來佈置所有組件。 (這將是我的最愛)
  4. 用一個X_AXIS用一個BoxLayout替換FlowLayout。

的rember是GridBagConstraints的屬性:

  • 的gridx,gridy:指定位置
  • gridwidth,gridheight:指定合併單元格/行跨度
  • 的weightx,份量:指定誰得到額外的水平/垂直空間和按什麼比例
  • anchor:指定組件與其「單元」的對齊,如果「單元」大於組件
  • 填充:指定組件是否應拉伸至單元寬度/高度
+0

+1,我喜歡這個答案,只是不知道,今天好像我很懶,應該提到有關設置尺寸的東西,然後我想,上帝知道OP在想什麼:-),所以離開了話題不變。 –

+0

感謝您的幫助。我會相應地修改代碼。關於重新使用GridBagConstraint,Oracle的網站建議不要這樣做,因爲一些舊的值可能會被錯誤地結轉。問候。 – Peter

+0

@彼得是的,這是真的。但是,當您在同一「行」上佈置多個組件時,我發現它有時很方便。但通常,我不會遇到這個問題,因爲我在循環中使用了相同的GridBagConstraint並從模型中獲取值。你應該選擇你更舒適的方式。 –

3

只是增加每一個JPanelCenter and Bottom會做的伎倆給你,所以直到你JTextAreaGridBagLayout將服務器的目的,之後的BorderLayout的主要JPanel會做。而且,在整個事情中增加JScrollPane也可以減少其他地區所需的工作量。看看代碼和輸出:

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

public class JTextPaneExample extends JPanel 
{ 
    private Icon info = UIManager.getIcon("OptionPane.informationIcon"); 
    private Icon error = UIManager.getIcon("OptionPane.errorIcon"); 

    private static JButton CreateImageButton(String fileName) { 
     JButton retVal = new JButton("xxx"); 
     return retVal; 
    } 

    private void createAndDisplayGUI() 
    { 
     JFrame frame = new JFrame("JTextPane Example"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     this.setLayout(new BorderLayout()); 
     this.setBackground(Color.WHITE); 

     JPanel centerPanel = new JPanel(); 
     centerPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 
     centerPanel.setLayout(new GridBagLayout()); 
     centerPanel.setBackground(Color.WHITE); 
     JButton btnRefresh = CreateImageButton("refresh.png"); 
     GridBagConstraints c = new GridBagConstraints(); 
     c.gridx=0; 
     c.gridy=0; 
     c.fill = GridBagConstraints.NORTH; 
     c.insets.left = 10; c.insets.right = 10; c.insets.top = 10; 
     centerPanel.add(btnRefresh, c); 

     JComboBox cbMovieList = new JComboBox(); 
     c = new GridBagConstraints(); 
     c.gridx = 1; 
     c.gridy = 0; 
     c.fill = GridBagConstraints.HORIZONTAL; 
     c.insets.right = 10; c.insets.top = 10; 
     c.weightx = 1.0; 
     centerPanel.add(cbMovieList, c); 

     JButton btnAuthorize = new JButton("Get Info"); 
     c = new GridBagConstraints(); 
     c.gridx = 1; 
     c.gridy = 1; 
     c.anchor = GridBagConstraints.WEST; 
     c.insets.top = 10; 
     centerPanel.add(btnAuthorize, c); 

     JTextArea txtInfo = new JTextArea(); 
     txtInfo.setFont(new Font("SansSerif", Font.BOLD, 12)); 
     txtInfo.setBackground(Color.cyan); 
     // txtInfo.setText("abc\ndef"); 
     txtInfo.setText("abc\ndef\nghi\njkl\nmno\npqr\nstu\nvwx\nyz"); 
     JScrollPane scroller = new JScrollPane(); 
     scroller.setViewportView(txtInfo); 
     c = new GridBagConstraints(); 
     c.gridx = 1; 
     c.gridy = 2; 
     c.anchor = GridBagConstraints.NORTHWEST; 
     c.fill = GridBagConstraints.HORIZONTAL; 
     c.weighty = 1.0; 
     c.insets.top = 10; 

     centerPanel.add(scroller, c); 

     JPanel controllerOuter = new JPanel(); 
     controllerOuter.setLayout(new BoxLayout(controllerOuter, BoxLayout.Y_AXIS)); 
     controllerOuter.setBorder(BorderFactory.createRaisedBevelBorder()); 

     FlowLayout controllerLayout = new FlowLayout(FlowLayout.CENTER); 
     controllerLayout.setHgap(0); 
     JPanel controller = new JPanel(controllerLayout); 

     controller.setBorder(new EmptyBorder(10, 10, 10, 10)); 

     Dimension dim = new Dimension(60, 40); 
     JButton btnPlay = CreateImageButton("play.png"); 
     btnPlay.setPreferredSize(dim); 

     controller.add(btnPlay); 
     JButton btnPause = CreateImageButton("pause.png"); 
     btnPause.setPreferredSize(dim); 
     controller.add(btnPause); 
     JButton btnStop = CreateImageButton("stop.png"); 
     btnStop.setPreferredSize(dim); 
     controller.add(btnStop); 
     JButton btnForward = CreateImageButton("forward.png"); 
     btnForward.setPreferredSize(dim); 
     controller.add(btnForward); 
     JComboBox cbAspectRatio = new JComboBox(); 
     cbAspectRatio.setPreferredSize(new Dimension(100, 40)); 
     cbAspectRatio.setBorder(new EmptyBorder(0, 10, 0, 0)); 
     controller.add(cbAspectRatio); 

     controllerOuter.add(controller); 

     JProgressBar pbProgress = new JProgressBar(0, 100); 
     pbProgress.setPreferredSize(new Dimension(350, 40)); 
     pbProgress.setBorder(new EmptyBorder(0, 10, 10, 10)); 
     pbProgress.setValue(50); 
     pbProgress.setString("50/100"); 
     pbProgress.setStringPainted(true); 
     pbProgress.setForeground(Color.BLUE); 
     pbProgress.setBorderPainted(true); 
     controllerOuter.add(pbProgress); 

     add(centerPanel, BorderLayout.CENTER); 
     add(controllerOuter, BorderLayout.PAGE_END); 

     frame.getContentPane().add(this); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String... args) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       new JTextPaneExample().createAndDisplayGUI(); 
      }   
     }); 
    } 
} 

這裏是因爲你增加更多的線路輸出:

LAYOUT

+0

+1。使用BorderLayout的好解決方案。簡單而簡單。 –

相關問題