【问题标题】:JPanel does not fill containing JFrameJPanel 不填充包含 JFrame
【发布时间】:2013-06-21 17:52:55
【问题描述】:

嗨,我正在编写一个简单的物理引擎来更好地理解对象碰撞和 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 和 jframe 容器之间有填充?这是一个默认边框,你可以改变它。
  • 我相信是的。我希望我能更好地问这个问题,但我不太明白自己发生了什么。在 JFrame 中,我希望面板起源于 JFrame 窗口的左上角,但它起源于 JFrame 本身的左上角(就像过去的边框一样)。我相信,正因为如此,我在面板的右侧和底部得到了白色填充,即使它应该都是黑色的。

标签: java swing jframe jpanel


【解决方案1】:

JPanelEnginePanel 的首选大小限制了面板调整大小,JFrame 呈现为不可调整大小。在调用setResizable(false) 后调用JFrame#pack。还要在打包后移动setLocationRelativeTo,使框架居中。

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

【讨论】:

  • 谢谢!所以这有助于 JPanel 的位置到我想要的位置,但是如果我要改变怎么办: FPSTextField = new TextField("Currnet FPS: " + currentFPS, 25, 25); to: FPSTextField = new TextField("当前 FPS:" + currentFPS, 0, 0); TextField 不显示?
  • 布局管理器使用0,0 作为JFrame 的最左上角。您必须考虑到窗户装饰的大小
  • 无论如何设置0,0作为窗口的左上角而不是JFrame,或者你如何找到装饰的大小?
  • 不是通过自定义绘制String,但您可以使用具有合适布局的JLabel,例如FlowLayout.LEFT 让布局管理器完成工作。要获得装饰的大小,请使用JFrame#getInsets
【解决方案2】:

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

此外,坐标对您来说似乎不正确的原因是您将其视为 (x, y) 坐标,而实际上它是 (row, col) 坐标,就像在 2D 数组中一样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    • 2016-06-08
    • 2021-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多