JPanel 不填充包含 JFrame



嗨,所以我正在编写一个简单的物理引擎来更好地理解对象碰撞和 Java 图形,到目前为止,我已经成功地编写了代码将 JPanel 添加到 JFrame 并允许它们显示一些正确的大小,但是当我查看实际程序时,JPanel 的大小似乎合适,但它没有从窗口的上角开始, 而是框架的左上角。我似乎经常遇到这个问题,我希望某些东西位于 (0, 0( 并从框架的上角而不是面板开始。这是我的代码:

我有一个扩展 JFrame 并包含 main 方法的引擎类 -->

package io.shparki.PhysicsEngine;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class Engine extends JFrame{
    public Engine(){
        super("Physics Engine and Simulator");
        setLayout(new BorderLayout());
        add(new EnginePanel(), BorderLayout.CENTER);
        pack();
        setResizable(false);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }
    public static void main(String[] args){
        new Engine();
    }
}

这是我的第二个类,EnginePanel,它扩展了JPanel并实现了Runnable -->

package io.shparki.PhysicsEngine;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import javax.swing.JPanel;

public class EnginePanel extends JPanel implements Runnable{
    private static final int WIDTH = 300;
    private static final int HEIGHT = WIDTH / 16 * 9;
    private static final int SCALE = 4;
    public int getWidth() { return WIDTH * SCALE; }
    public int getHeight() { return HEIGHT * SCALE; }
    @Override
    public Dimension getPreferredSize(){ return new Dimension(WIDTH * SCALE, HEIGHT * SCALE); }
    private static final int FPS = 85;
    private static final int PERIOD = 1000 / FPS;
    private int currentFPS = 0;
    private Thread animator;
    private boolean running = false;
    private Graphics dbg;
    private Image dbImage = null;

    public EnginePanel(){
        setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
        setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
        setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
        setVisible(true);
    }
    public void addNotify(){
        super.addNotify();
        startEngine();
    }
    public void startEngine(){
        running = true;
        animator = new Thread(this, "Animator");
        animator.start();
    }
    public void stopEngine(){
        running = false;
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        if (dbImage != null){
            g.drawImage(dbImage,  0,  0,  null);
        }
    }
    public void paintScreen(){
        Graphics g;
        try{
            g = this.getGraphics();
            if ( g != null && dbImage != null){
                g.drawImage(dbImage, 0, 0, null);
            }
            Toolkit.getDefaultToolkit().sync();
            g.dispose();
        } catch(Exception ex) { System.out.println("Graphics Context Error : " + ex); }
    }
    public void run(){
        running = true;
        init();
        Long beforeTime, timeDiff, sleepTime;
        while(running){
            beforeTime = System.currentTimeMillis();
            updateEngine();
            renderEngine();
            paintScreen();
            timeDiff = System.currentTimeMillis() - beforeTime;
            sleepTime = PERIOD - timeDiff;
            if (sleepTime <= 0){
                sleepTime = 5L;
            }
            currentFPS = (int) (1000 / (sleepTime + timeDiff));
            try{
                Thread.sleep(sleepTime);
            } catch (InterruptedException ex) { ex.printStackTrace(); }
        }
    }


    private TextField FPSTextField;

    public void init(){
        FPSTextField = new TextField("Currnet FPS: " + currentFPS, 25, 25);
    }
    public void updateEngine(){
        FPSTextField.setText("Currnet FPS: " + currentFPS);
    }
    public void renderEngine(){
        if (dbImage == null){
            dbImage = createImage((int)getWidth(), (int)getHeight());
            if (dbImage == null){
                System.out.println("Graphical Context Error : DBImage is Null");
                return;
            } else {
                dbg = dbImage.getGraphics();
            }
        }
        Graphics2D g2d = (Graphics2D) dbg;
        g2d.setColor(Color.BLACK);
        g2d.fillRect(0, 0, getWidth(), getHeight());
        FPSTextField.render(g2d, Color.MAGENTA);
    }
}

我不太确定为什么这种情况不断发生,我已经寻求帮助,但找不到答案。提前感谢所有帮助:)的人

编辑:为TextField对象添加了代码:

package io.shparki.PhysicsEngine;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
public class TextField{
    private Point location;
    public Point getLocation(){ return location; }
    public double getX() { return location.getX(); }
    public double getY() { return location.getY(); }
    private String text;
    public void setText(String text) { this.text = text; }
    public String getText() { return this.text; }
    public TextField(String text, int x, int y){
        this.location = new Point(x, y);
        this.text = text;
    }
    public TextField(String text, Point location){
        this.location = location;
        this.text = text;
    }

    public void render(Graphics g){
        g.drawString(text, (int)location.getX(), (int)location.getY());
    }
    public void render(Graphics2D g2d){
        g2d.drawString(text, (int)location.getX(), (int)location.getY());
    }
    public void render(Graphics g, Color color){
        g.setColor(color);
        g.drawString(text, (int)location.getX(), (int)location.getY());
    }
    public void render(Graphics2D g2d, Color color){
        g2d.setColor(color);
        g2d.drawString(text, (int)location.getX(), (int)location.getY());
    }
    public void render(Graphics g, Color color, Font font){
        g.setColor(color);
        g.setFont(font);
        g.drawString(text, (int)location.getX(), (int)location.getY());
    }
    public void render(Graphics2D g2d, Color color, Font font){
        g2d.setColor(color);
        g2d.setFont(font);
        g2d.drawString(text, (int)location.getX(), (int)location.getY());
    }
}

JPanel EnginePanel的首选大小限制面板的大小,JFrame不可调整大小。调用setResizable(false)后调用JFrame#pack。在包装后移动setLocationRelativeTo,使框架显示为居中。

pack();
setLocationRelativeTo(null);
setVisible(true);

如果您在 JFrame 中使用 GridBagLayout,那么如果 JPanel 是您添加到 JFrame 中的唯一内容,则 JPanel 将居中。如果您调整窗口大小,它甚至会停留在中心。

此外,坐标对您来说似乎不对的原因是您将其视为 (x, y( 坐标,而它实际上是 2D 数组中的(行,列(坐标。

最新更新