嗨,所以我正在编写一个简单的物理引擎来更好地理解对象冲突和Java图形,到目前为止,我已成功编写代码将JPanel添加到JFrame并允许它们显示正确的大小,但是当我查看实际程序时,JPanel似乎是正确的大小,但它不是从窗口的上角开始,而是从框架的左上角开始。我似乎有这个问题很多我想要的东西在(0,0),并开始在框架的上角而不是面板。这是我的代码:
我有一个扩展JFrame的引擎类,包含主要方法 - >
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());
}
}
答案 0 :(得分:3)
JPanel
EnginePanel
的首选大小限制了面板的大小调整JFrame
呈现不可调整大小。在致电JFrame#pack
后调用setResizable(false)
。同时在包装后移动setLocationRelativeTo
,使框架显示为居中。
pack();
setLocationRelativeTo(null);
setVisible(true);
答案 1 :(得分:0)
如果在JFrame中使用GridBagLayout,那么如果它是您添加到JFrame的唯一内容,则JPanel将居中。如果你调整窗口大小,它甚至会留在中心。
此外,坐标似乎不适合您的原因是您将其视为(x,y)坐标,而实际上它是一个(行,col)坐标,就像在2D数组中一样。