JFrame向帧顶部添加22像素偏移量(java.awt.Insets)

JFrame向帧顶部添加22像素偏移量(java.awt.Insets),java,swing,jframe,jpanel,awt,Java,Swing,Jframe,Jpanel,Awt,我正在创建一个简单的爆发式游戏。主游戏扩展了JFrame,我在框架中添加了一个JPanel 当我使用paint()绘制游戏图形时,项目按预期放置在窗口内(即通过其x,y坐标) 我已经更新了代码以使用BufferStrategy,因为我正在闪烁。由于,渲染的图形偏移了22px 这意味着砖块离开了屏幕的顶部 代码如下: package BreakOut; import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent

我正在创建一个简单的爆发式游戏。主游戏扩展了JFrame,我在框架中添加了一个JPanel

当我使用paint()绘制游戏图形时,项目按预期放置在窗口内(即通过其x,y坐标)

我已经更新了代码以使用BufferStrategy,因为我正在闪烁。由于,渲染的图形偏移了22px

这意味着砖块离开了屏幕的顶部

代码如下:

package BreakOut;

import javax.swing.*;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;


public class Game extends JPanel implements KeyListener{

GameStateManager gsm = new GameStateManager();
BufferStrategy strategy;

public Game() {

    //add menu state to GameStateManager
    gsm.add(new MenuState(gsm));
    createFrame();


    while(true)
    {
        gsm.update();
        //repaint();
        render();
        try{
            Thread.sleep(10);
        }
        catch(InterruptedException e)
        {

        }
    }
}


public void createFrame()
{
    JFrame frame = new JFrame("Mini Tennis");
    frame.setLayout(new BorderLayout());
    this.setPreferredSize(new Dimension(400,400));
    frame.add(this);        
    frame.pack();       
    frame.setBackground(Color.BLACK);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    addKeyListener(this);
    this.setFocusable(true);
    frame.createBufferStrategy(2);
    strategy = frame.getBufferStrategy();
    frame.setVisible(true);
    System.out.println(frame.getInsets());
}


public void render()
{
    Graphics g = strategy.getDrawGraphics();
    super.paint(g);
    gsm.render(g);
    g.dispose();
    strategy.show();
}


public void keyPressed(KeyEvent k) {
    switch(gsm.getState())
    {
        case MAIN_MENU:
        if(k.getKeyCode()==KeyEvent.VK_ENTER)
        {
            //add the PlayState to the Stack and update enum value
            gsm.add(new PlayState(gsm, this));
        }
        break;
        case PLAYING:
            if(k.getKeyCode()==KeyEvent.VK_P)
            {
                //add the PlayState to the Stack and update enum value
                gsm.add(new PauseState(gsm));
            }
            break;
        case PAUSE:
            if(k.getKeyCode()==KeyEvent.VK_P)
            {                   
                gsm.pop();
            }
            break;
        case GAME_OVER:
            if(k.getKeyCode()==KeyEvent.VK_ENTER)
            {                   
                gsm.pop();
            }
            break;
    }
    //send input to GameStateManager
    gsm.keyPressed(k.getKeyCode()); 
}

public void keyReleased(KeyEvent k) {
    gsm.keyReleased(k.getKeyCode());        
}

public void keyTyped(KeyEvent k) {
    gsm.keyTyped(k.getKeyCode());   
}


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

}
}

当我输出System.out.println(frame.getInsets())时;我明白了

我显然做错了什么,但不明白为什么添加BufferStrategy会使JPanel被22px抵消


任何帮助都将不胜感激:)

从您使用MacOS的外观来看,框架有边框和装饰,这些边框和装饰包含在框架的边界内(它们不会添加到外部),顶部的22像素是窗口标题

最好的解决方案是,不要使用帧作为渲染曲面,而是使用
游戏
类。这意味着它需要从
java.awt.Canvas
扩展,而不是从
javax.swing.JPanel
扩展,您需要从它创建
BufferStrategy

如果您覆盖
Canvas
getPreferredSize
方法,您可以在框架上使用
pack
,它将围绕此框架打包窗口,因此物理框架将比内容大,但内容将是您喜欢的大小


您还需要将主/游戏循环移动到单独的线程,因为这是当前阻止事件调度线程的风险,这可能会导致您无休止的问题(例如从未获得关键事件)

太好了,谢谢:)线程是我列表中的下一个事项。在游戏循环中使用线程的最佳方法是什么?我会实现Runnable吗?通常,是的,通常建议使用
Runnable
,并将其传递给
线程的实例(通过其构造函数)。请记住,Swing不是线程安全的,但由于您使用的是
缓冲策略
,这不应该成为问题,因为
缓冲策略
和Swing组件不能很好地配合使用。再次感谢:)因此,对于游戏,您通常会使用画布渲染游戏图形吗?像libgdx这样的游戏库是否有自己创建窗口和绘制屏幕的方法,或者是否使用Swing和AWT?游戏工具包可能依赖于
画布和
缓冲策略,或者提供自己的本地对等方,这些对等方将连接到
画布,具体取决于那里实现
java.awt.Insets[top=22,left=0,bottom=0,right=0]