2013-06-21 95 views
1

嗨,所以我正在写一个简单的物理引擎来理解对象冲突和Java图形好一点,到目前为止,我已经成功地编写了代码添加JPanel到JFrame,并允许他们显示出正确的大小,但是当我查看实际的程序时,JPanel似乎是正确的大小,但它不是从窗口的上角开始,而是从帧的左上角开始。我似乎有这个问题很多,我想要的东西在(0,0),并开始在框架的上角而不是面板。这里是我的代码:JPanel不填充包含JFrame

我有一个扩展的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(); 
    } 

} 

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

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

如果我正确理解你的问题,你问为什么jpanel和jframe容器之间有填充?这是一个默认边框,你可以改变它。 – arynaq

+0

我相信如此。我希望我能更好地提出这个问题,但我不太明白自己在做什么。在JFrame中,我希望面板起源于JFrame窗口的左上角,但是它起源于JFrame本身的左上角(如过去的边框)。我相信,由于这个原因,我在面板的右侧和底部得到了白色的衬垫,尽管它们全都是黑色的。 –

回答

3

JPanelEnginePanel的首选大小限制从被调整的JFrame呈现不可调整大小的面板。在致电setResizable(false)后调用JFrame#pack。包装后也移动setLocationRelativeTo,以使框架显示居中。

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

谢谢!因此,这有助于将JPanel的位置设置到我想要的位置,但是如果我要更改,将会如何: FPSTextField = new TextField(“Currnet FPS:”+ currentFPS,25,25); 至: FPSTextField = new TextField(“Currnet FPS:”+ currentFPS,0,0); TextField不显示? –

+1

布局管理器使用'0,0'作为JFrame的最左上角。你必须允许窗口装饰的大小 – Reimeus

+0

有无论如何设置0,0作为窗口的左上角而不是JFrame,或者你会如何找到装饰的大小? –

0

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

此外,坐标显示给你的原因是,你正在将它看作一个(x,y)坐标,而它实际上是一个像2D数组中的(行,列)坐标。