2013-07-13 94 views
4

我遇到了GridLayout的问题,并且没有填充整个JPanel。我有一个N * M网格,我用N * M Tiles填充(它们扩展了JPanel)。添加所有这些瓷砖后,JPanel的底部和右侧仍有空间。我认为GridLayout应该填满整个JPanel,并使其中的所有内容均匀大小?GridLayout未填充JPanel

编辑:我不想发布所有的代码,因为有多个类。想想也许有一个简单的解决方案。

public class MainFrame extends JFrame { 

    private static final long serialVersionUID = 3985493842977428355L; 
    private final int FRAME_HEIGHT = 800; 
    private final int FRAME_WIDTH = 700; 

    private MainPanel mainPanel; 

    public MainFrame() { 
     super("Test"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setSize(FRAME_HEIGHT, FRAME_WIDTH); 
     setLocationRelativeTo(null);  
     mainPanel = new MainPanel(); 
     getContentPane().add(mainPanel); 
     setVisible(true); 
    } 
} 

public class MainPanel extends JPanel { 
    /** 
    * 
    */ 
    private static final long serialVersionUID = 3421071253693531472L; 

    private RoutePanel routePanel; 
    private ControlPanel controlPanel; 
    private GridBagConstraints gridBagConstraints; 
    private GridBagLayout gridBagLayout; 

    public MainPanel() { 
     routePanel = new RoutePanel(); 
     controlPanel = new ControlPanel(); 
     setBackground(Color.black); 
     gridBagLayout = new GridBagLayout(); 
     setLayout(gridBagLayout); 
     gridBagConstraints = new GridBagConstraints(); 
     createLayout(); 
    } 

    private void createLayout() { 
     gridBagConstraints.weightx = 1; 
     gridBagConstraints.weighty = 1; 
     gridBagConstraints.gridx = 0; 
     gridBagConstraints.gridy = 0; 
     gridBagConstraints.anchor = GridBagConstraints.NORTH; 
     gridBagConstraints.fill = GridBagConstraints.BOTH; 
     gridBagLayout.setConstraints(routePanel, gridBagConstraints); 
     add(routePanel); 

     gridBagConstraints.weightx = 1; 
     gridBagConstraints.weighty = .05; 
     gridBagConstraints.gridx = 0; 
     gridBagConstraints.gridy = 1; 
     gridBagConstraints.anchor = GridBagConstraints.SOUTH; 
     gridBagConstraints.fill = GridBagConstraints.BOTH; 
     gridBagLayout.setConstraints(controlPanel, gridBagConstraints); 
     add(controlPanel); 
    } 
} 

public class RoutePanel extends JPanel{ 
    /** 
    * 
    */ 
    private static final long serialVersionUID = 4366703088208967594L; 
    private final int GRID_ROWS = 30; 
    private final int GRID_COLS = 47; 


    public RoutePanel() { 
     setLayout(new GridLayout(GRID_ROWS, GRID_COLS, 0, 0)); 
     for(int i = 0; i < GRID_ROWS * GRID_COLS; i++) { 
      add(new Tile()); 
     } 
     setBackground(Color.orange); 
    } 
} 

public ControlPanel() { 

    } 

public Tile() { 
     setBackground(Color.gray); 
     Border blackline; 
     blackline = BorderFactory.createLineBorder(Color.black); 
     setBorder(blackline); 
    } 
+0

下一次,请显示SSCCE(上面没有) - 特别是布局问题不能完全支持没有 – kleopatra

回答

7

由于您没有发布代码,我们被迫猜测(这不是很好)。

我的猜测是:您可能正在设置一些组件或GUI的大小或首选大小,这会在GUI的边缘造成间隙。

解决方法:不要这样做。在GUI上调用pack()时,让组件通过它们的首选大小和布局管理器自行调整大小。

如需更多帮助,请创建并发布您的sscce。对于这样的问题,代码确实是强制性的,而且我实际上有点惊讶,你没有发布你的代码。


编辑1

例如,注意在差的GUI的制作:

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.GridLayout; 

import javax.swing.*; 

public class GapExample { 
    private static final int M = 5; 
    private static final int N = 6; 
    private static final int PREF_W = 700; 
    private static final int PREF_H = 500; 

    @SuppressWarnings("serial") 
    private static void createAndShowGui() { 

     // *** attempt 1: set preferredSize of the mainPanel JPanel *** 
     JPanel mainPanel = new JPanel(new GridLayout(M, N)); 
     mainPanel.setBorder(BorderFactory.createLineBorder(Color.red)); 
     mainPanel.setPreferredSize(new Dimension(PREF_W, PREF_H)); 

     for (int i = 0; i < M; i++) { 
     for (int j = 0; j < N; j++) { 
      String text = String.format("Foo [%d, %d]", i, j); 
      JLabel label = new JLabel(text, SwingConstants.CENTER); 
      label.setBorder(BorderFactory.createLineBorder(Color.blue)); 
      mainPanel.add(label); 
     } 
     } 
     JOptionPane.showMessageDialog(null, mainPanel, 
      "Attempt 1, setPreferredSize of mainPane", 
      JOptionPane.PLAIN_MESSAGE); 

     // *** attempt 2: override the getPreferredSize of the JLabel cells in the 
     // grid *** 
     mainPanel = new JPanel(new GridLayout(M, N)); 
     mainPanel.setBorder(BorderFactory.createLineBorder(Color.red)); 
     final Dimension labelPrefSize = new Dimension(PREF_W/N, PREF_H/M); 
     for (int i = 0; i < M; i++) { 
     for (int j = 0; j < N; j++) { 
      String text = String.format("Foo [%d, %d]", i, j); 
      JLabel label = new JLabel(text, SwingConstants.CENTER) { 
       @Override 
       public Dimension getPreferredSize() { 
        return labelPrefSize; 
       } 
      }; 
      label.setBorder(BorderFactory.createLineBorder(Color.blue)); 
      mainPanel.add(label); 
     } 
     } 
     JOptionPane 
      .showMessageDialog(null, mainPanel, 
        "Attempt 2, override getPreferredSize of the JLabel cells in the grid", 
        JOptionPane.PLAIN_MESSAGE); 
    } 

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

在第二个对话框,我中的JLabel返回一个优选的大小,让容器它们让它们设置最佳尺寸来显示GUI,并且在第二次尝试时,网格会更好。

这将显示第一(坏)尝试内部与外部部件之间的间隙:

enter image description here

第二(好)尝试,并显示没有这样的间隙:

enter image description here

+0

我有一个包的问题是它调整了一切,并使GUI非常小。 – Taztingo

+1

@ user1932934您使用包的问题是,您的子组件未向布局管理器提供足够准确的信息,以便他们针对程序的整体大小作出适当决策。 – MadProgrammer

+0

@ user1932934:请参阅编辑以进行回答。 –

3

GridLayout应该填满整个JPanel,并且使其中的所有物品均匀大小

这两个是相反的力量,管理者可以在只有当面板宽度为列宽的倍数,同时做到既:

panel.width == column.width * column.count 

如果这是不可能的,这有利于平等-size约束,通过调整儿童的最大宽度来使它们相等,并将整个块定位在父母的中心,从而暴露父母的背景。基本上,你所看到的整数运算的效果:-)


至于discussion in the other answer

第一关:我拿上setXXSize是众所周知的 - it's always wrong to use in application code我认为这是一个设计的事故,不应该首先发生了,因为大多数时候它引入了比看起来(表面上的!)更多的问题来解决。

下一个最接近的解决方案似乎覆盖getXXSize:如果做返回任意硬编码固定大小,它只是比调用setXXSize(在不传播最坏的做法:)稍好一点:返回值应该与内部状态。它应该保持超级完整的内部计算(如果有的话)并且可以修改它。另外严格地说,应该遵守超的合同这的确规定(有点隐藏在setXXSize),其通过应用setXXSize尺寸优先

设置此组件的首选大小设置为常值。 随后对getPreferredSize的调用将始终返回此值。

在代码:

// always wrong in application code 
someComponent.setPreferredSize(labelPrefSize); 

// suboptimal: arbitrary hard-coded fixed size 
@Override 
public Dimension getPreferredSize() { 
    return new Dimension(labelPrefSize); 
} 

// good: fixed value based on internal state 
@Override 
public Dimension getPreferredSize() { 
    return new Dimension(labelPrefSize); 
} 
// the size has some meaning f.i. when painting 
@Override 
protected void paintComponent(Graphics g) { 
    g.drawRect(0, 0, labelPrefSize.width, labelPrefSize.height); 
} 

// good: prefsize relative to super's calculation 
@Override 
public Dimension getPreferredSize() { 
    Dimension labelPrefSize = super.getPreferredSize(); 
    int maxSide = Math.max(labelPrefSize.width, labelPrefSize.height); 
    labelPrefSize.setSize(maxSide, maxSide); 
    return labelPrefSize; 
} 

// better: prefsize relative to default calculation 
// _and_ comply to super's contract 
@Override 
public Dimension getPreferredSize() { 
    Dimension labelPrefSize = super.getPreferredSize(); 
    if (isPreferredSizeSet()) return labelPrefSize; 
    // any of the good thingies ... 
} 

理想的情况是,你不会触及大小的内部计算在所有暗示。相反,使用LayoutManager可以对布局进行微调,使其完全符合您的需求。请记住:管理程序将提示和自由大小但是她反正喜欢:-)

更新

编辑上面试图强调“相关内部状态”啄:施胶提示应返回他们自己孤立的,以自我为中心的需求而不关心上下文。因此,压倒一切的回报外部需求是不理想的。