如何使JFrame内的JPanel填满整个窗口?

5
在下面的例子中,我该如何让JPanel占据整个JFrame?我将首选大小设置为800x420,但它实际上只填充了792x391。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class BSTest extends JFrame {
    BufferStrategy bs;
    DrawPanel panel = new DrawPanel();

    public BSTest() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());   // edited line
        setVisible(true);
        setSize(800,420);
        setLocationRelativeTo(null);
        setIgnoreRepaint(true);
        createBufferStrategy(2);
        bs = getBufferStrategy();
        panel.setIgnoreRepaint(true);
        panel.setPreferredSize(new Dimension(800,420));
        add(panel, BorderLayout.CENTER);     // edited line
        panel.drawStuff();
    }

    public class DrawPanel extends JPanel {
        public void drawStuff() {
            while(true) {
                try {
                    Graphics2D g = (Graphics2D)bs.getDrawGraphics();
                    g.setColor(Color.BLACK);
                    System.out.println("W:"+getSize().width+", H:"+getSize().height);
                    g.fillRect(0,0,getSize().width,getSize().height);
                    bs.show();
                    g.dispose();
                    Thread.sleep(20);
                } catch (Exception e) { System.exit(0); }
            }
        }
     }

    public static void main(String[] args) {
        BSTest bst = new BSTest();
    }
}

1
Swing引擎有自己的绘制循环,您不需要使用while(true)。只需在面板类中覆盖JComponent.paint(Graphics g)即可。 - Joe Coder
嗨@Joe,我正在尝试在这里使用BufferStrategy,因此您不使用paint(),这就是while()循环和setIgnoreRepaint(true);的原因。有什么办法可以填满整个窗口吗? - flea whale
是的,请尝试将您的JPanel传递给JFrame.setContentPane() - Joe Coder
4个回答

6

如果您的框架中只有一个面板,没有其他任何东西,请尝试以下操作:

  • 在框架中设置边框布局。
  • 使用BorderLayout.CENTER将面板添加到框架中

可能是因为JPanel中的while循环导致了这个问题。(不确定原因?正在寻找实际原因。找到后会更新。)如果用paintComponent(g)方法替换它,一切都正常工作:

public BSTest() {
    //--- your code as it is
    add(panel, BorderLayout.CENTER);
    //-- removed panel.drawStuff();
}

public class DrawPanel extends JPanel {
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.BLACK);
        System.out.println("W:" + getSize().width + ", H:" + getSize().height);
        g2d.fillRect(0, 0, getSize().width, getSize().height);
    }
 }

//your code as it is.

嗨@Harry,我刚刚尝试了你的建议(请参见上面代码中的新编辑行),但它显示的完全相同! - flea whale
谢谢,但我正在尝试使用BufferStrategy制作游戏,因此您不需要使用paintComponent,您首先绘制内容,然后使用bs.show()翻转缓冲区。 - flea whale

3
这里提供一个使用pack代替的替代方案。
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class PackExample extends JFrame {

    public PackExample(){
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(800,600));
        panel.setBackground(Color.green);
        add(panel);
        pack();
        setVisible(true);
   }

   public static void main(String[] args){
     new PackExample();
   }

}

对于 pack() 使用 +1;对于错误使用 setPreferredSize()(参见 https://dev59.com/BGw05IYBdhLWcg3weBlF)使用 -1。 - trashgod
@trashgod DYM 1)使用高级布局(也称为“kleopatra方法”)2)覆盖getPreferredSize()3)还有其他吗?由于1)需要第三方布局,因此无法在核心J2SE中完成(这可能是一个问题或不是问题)。2)使组件的首选大小不灵活。我更喜欢像jtp一样设置大小。+1 - Andrew Thompson
1
@AndrewThompson:谢谢您的详细解释。我指的是2)在这里所示的意义上覆盖getPreferredSize(),并在这里的第一条中提到。我认为在这种情况下未经解释的setPreferredSize()可能会产生误导。这取决于面板中有什么:更多组件→ setPreferredSize()不好;只是绘画→ setPreferredSize()可以。 - trashgod
1
@trashgod 谢谢您的澄清。在浏览了 OP 的代码(并看到 BufferStrategy)后,我决定除了“只是绘画”之外几乎没有其他可能性。然而现在我想想,对于“只是绘画”,一个 JComponent 通常就足够了。此外,“未解释”的词汇表明答案可能会被编辑为带有代码注释以使上下文更加清晰。 - Andrew Thompson

3
这让我花了很长时间才理解,但其实这是最简单的代码。只需创建一个父面板并传递GridLayout,然后像这样添加您的子面板。
JPanel parentPanel= new JPanel(new GridLyout());
JPanel childPanel= new JPanel();
parentPanel.add(childPanel);

似乎默认使用的FlowLayout会尝试将所有内容压缩得尽可能小。即使是BorderLayout也可以解决这个问题。 - user515655

1
如果您想要将JFrame填满整个JPanel,您需要将setUndecorated设置为true,即frame.setUndecorated(true);。但现在您需要担心最大化、最小化和关闭按钮,位于右上角(Windows操作系统)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接