JFrame 将 22 像素偏移量 (java.awt.Insets) 添加到 Frame 顶部

2022-01-24 00:00:00 java swing jpanel jframe awt

我正在创建一个简单的 Break Out 风格的游戏.主游戏扩展了 JFrame,我在框架中添加了一个 JPanel.

I'm creating a simple Break Out style game. The main game extends JFrame and I'm adding a JPanel to the frame.

当我使用paint() 绘制游戏图形时,项目按预期位于窗口内(即通过它们的x、y 坐标).

When I was using paint() to draw the game graphics the items sat within the window as expected (i.e by their x, y coordinates).

我更新了代码以使用 BufferStrategy,因为我正在闪烁.从那以后,渲染的图形偏移了 22px.

I've updated the code to use BufferStrategy as I was getting flickering. Since the, the graphics that are rendered are offset by 22px.

这意味着砖块不在屏幕顶部!

This means the Bricks are off the top of the screen!

代码如下:

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());我明白了

When I output System.out.println(frame.getInsets()); I get

java.awt.Insets[top=22,left=0,bottom=0,right=0]

我显然做错了什么,但无法弄清楚为什么添加 BufferStrategy 会创建 JPanel 偏移 22px

I'm obviously doing something wrong but can't figure out why adding BufferStrategy would create the JPanel to be offset by 22px

任何帮助将不胜感激:)

Any help would be appreciated :)

推荐答案

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

Frames have borders and decorations, which is included within the bounds of the frame (they don't get added to the outside), from the looks of things you're using MacOS and the 22pixels to the top is the window title.

最好的解决方案是,不要使用框架作为渲染表面,而是使用 Game 类.这意味着它需要从 java.awt.Canvas 而不是 javax.swing.JPanel 扩展,并且您需要创建 BufferStrategy来自它

Best solution is, don't use the frame as the render surface, instead, use the Game class. This will mean it will need to extend from java.awt.Canvas instead of javax.swing.JPanel and you will need to create the BufferStrategy from it

如果你重写了 CanvasgetPreferredSize 方法,你可以在框架上使用 pack ,它会围绕这个打包窗口,所以物理框架会比内容大,但内容将是您喜欢的大小

If you override the Canvas's getPreferredSize method, you can use pack on the frame it will pack the window around this, so the physical frame will be larger then the content, but the content will be the size you would prefer

您还需要将主/游戏循环移动到单独的线程,因为这是当前存在阻塞事件调度线程的风险,这可能会导致您无法解决问题(例如永远不会收到关键事件)

You will also want to move you main/game loop to separate thread, as this is current in the risk of blocking the Event Dispatching Thread, which could cause you no end of issues (like never getting a key event)

相关文章