2009-10-20 130 views
3

我创建了一个带有JPanel的窗体,里面有一些图形和一些按钮来控制事物。出于某种原因,我必须指定JPanel的宽度比要放入其中的实际图形小10px,并且低30px。什么导致这个问题?JPanel周围不需要的边框

这是代码:

public class Window { 
public Sheepness sheepness; 

public ButtonPanel buttonPanel; 
public PaintPanel paintPanel; 
public JFrame frame; 

public Window(Sheepness sheepness) { 
    this.sheepness = sheepness; 

    frame = new JFrame("Sheepness simulation"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    //frame.setSize(width, height); 

    BorderLayout frameLayout = new BorderLayout(); 
    JPanel background = new JPanel(frameLayout); 
    background.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 

    buttonPanel = new ButtonPanel(this); 
    background.add(BorderLayout.SOUTH, buttonPanel.buttonBox); 

    paintPanel = new PaintPanel(this); 
    paintPanel.setPreferredSize(new Dimension(320, 240)); 
    background.add(BorderLayout.CENTER, paintPanel); 

    frame.getContentPane().add(background); 
    frame.pack(); 
    frame.setResizable(false); 
    frame.setVisible(true); 
} 
} 

public class PaintPanel extends JPanel { 
public Window window; 

public PaintPanel(Window window) { 
    this.window = window; 
} 

@Override 
public void paintComponent(Graphics g) { 
    g.setColor(Color.blue); 
    g.fillRect(0, 0, 320, 240); 
} 
}

截图为320×240一个首选大小:

Can't find source image http://www.cmbi.ru.nl/~estens/Sheepness/Sheepness_simulation_border.png

您可以看到320 x 240 fillRect未完全填充JPanel,仍​​保留10 px宽度和30 px高度的边框。

截图与310 X 210使用preferredSize:

Can't find source image http://www.cmbi.ru.nl/~estens/Sheepness/Sheepness_simulation_noBorder.png

现在它正好适合320 x 240 fillRect!

任何想法?

+0

尝试添加'Border'('BorderFactory.createLineBorder(Color.RED,1)')围绕'paintPanel'这样就可以排除用'buttonPanel'相互作用。 – 2009-10-20 12:19:11

+0

我用setPreferredSize:参数:宽度:640,高度:480,在setPreferredSize和setSize:Width:640,Height:480,frame.pack:Width:650,Height:510之后设置它后,检查了JPanel的大小。我想它与包装一切的算法有关。不过,尺寸增加并不奇怪吗?有没有办法告诉事情停止触摸我的组件的大小,只是他们的路线?我认为这应该是setPreferredSize,但我猜这不符合它的要求。 – FinalArt2005 2009-10-20 13:21:18

+0

顺便说一句,添加边框显示与buttonPanel没有任何交互,因为它显示JPanel与按钮很好地排列在一起,但正如您可以从之前的注释中读取的那样,JPanel本身在打包后尺寸错误。 – FinalArt2005 2009-10-21 17:26:34

回答

3

不同的布局管理器使用不同的规则来计算实际的托管控件大小,也就是说,只有当您调用'setPreferredSize()'时,才能期望面板具有特定大小。

随时在所有特定情况下检查所有目标布局管理器的javadoc以获取有关已使用算法的更多详细信息。

另请注意,您可以避免使用布局管理器,并通过'setBounds()'方法绝对定义所有尺寸。

0

我想你的屏幕截图上的标签错了。

如果指定

g.fillRect(0, 0, 310, 210); 
在PaintPanel

paintPanel.setPreferredSize(new Dimension(320, 240)); 
在窗口

。你得到了第一个截图显示的内容。这是有道理的,因为矩形的宽度减少了10px,高度减少了30px。

如果你为两者设置相同的宽度/高度; 310,210,蓝色的矩形显然会“填充”PaintPanel。

+0

不,它是向后的:它将fillRect设置为0,0,320,240,并将preferredSize设置为310,210,您将获得填充的屏幕截图,同样的尺寸可以获得边框,这正是我的问题所在。 – FinalArt2005 2009-10-20 12:28:01

1

这里是一个自包含的测试用例,根据您的代码:

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

public class Test { 

public PaintPanel paintPanel; 
public JFrame frame; 

public Test() { 
    frame = new JFrame("Sheepness simulation"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    //frame.setSize(width, height); 

    BorderLayout frameLayout = new BorderLayout(); 
    JPanel background = new JPanel(frameLayout); 
    background.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 

    paintPanel = new PaintPanel(this); 
    paintPanel.setPreferredSize(new Dimension(320, 240)); 
    background.add(BorderLayout.CENTER, paintPanel); 

    frame.getContentPane().add(background); 
    frame.pack(); 
    frame.setResizable(false); 
    frame.setVisible(true); 
} 

    public static class PaintPanel extends JPanel { 
    public Test window; 

    public PaintPanel(Test window) { 
    this.window = window; 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
    g.setColor(Color.blue); 
    g.fillRect(0, 0, 320, 240); 
    } 
    } 

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

当我上的IcedTea JVM在Linux上运行它,我看到this

您的问题是由于按钮容器迫使窗口变宽,或者可能是由于您使用的Java版本中存在Swing错误。

我的建议是不要打扰内置布局类,而是使用MigLayout。

+0

我正在使用Sun Java 6.我还没有检查过按钮容器,但由于两种情况都使用完全相同的按钮容器,因此似乎不太可能是问题所在。这不是我想要解决的问题(我可以减小首选大小以使其工作),但我想知道是什么原因造成的。 – FinalArt2005 2009-10-20 12:32:17

+0

我想对上面的评论之一发表评论,但可以在那里评论... 几乎所有的布局管理器都忽略了最大和最小尺寸,有些并没有完全按照您期望的尺寸进行设计。 MigLayout尊重所有这些。这会让你的东西非常接近你要找的东西: background.setLayout(new MigLayout(“ins 5”)); background.add(paintPanel,“w 320!,h 240!,wrap”); background.add(buttonPanel,“gapabove unrel”); http://www.migcalendar.com/miglayout/ – uckelman 2009-10-20 18:19:59

2

信不信由你,但尝试反向包()和setResizeable()

... 
    frame.setResizable(false); 
    frame.pack(); // should be called after any changes 
    frame.setVisible(true); 

编辑的顺序:选中使用此

frame.pack(); 
    frame.setResizable(false); 
    System.out.println(paintPanel.getSize()); 
    frame.setVisible(true); 
    System.out.println(paintPanel.getSize()); 

frame.setResizable(false); 
    frame.pack(); 
    System.out.println(paintPanel.getSize()); 
    frame.setVisible(true); 
    System.out.println(paintPanel.getSize()); 

但如果大小不重要,您可以填写实际区域

@Override 
public void paintComponent(Graphics g) { 
    g.setColor(Color.blue); 
    g.fillRect(0, 0, getWidth(), getHeight()); 
} 

[]]

+0

感谢您的提示,但它也没有摆脱边界。 – FinalArt2005 2009-10-20 13:44:17

+0

在这里工作正常,没有ButtonPanel(没有代码),我只是得到了5x5边框(EmptyBorder)。在Windows XP上使用Java build 1.6.0_16-b01 – 2009-10-20 13:51:26

+0

我刚刚发布setResizable(false)正在影响这一点。如果setResizable(false)/ pack()的顺序相反,我也看到它正常工作 - Windows Vista上的JDK 1.5.0_16。 – Nate 2009-10-20 14:11:31