[英]JFrame getHeight() and getWidth() return 0
I'm making a simple pong game; 我正在做一个简单的乒乓球比赛; and part of the collision mechanics require getting the width and height of the canvas to redirect the ball.
并且部分碰撞力学需要获得画布的宽度和高度以重定向球。 However,
getWidth()
and getHeight()
return 0 for some reason. 但是,
getWidth()
和getHeight()
由于某种原因返回0。 Here's the main block of code. 这是主要的代码块。
package pong;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends JPanel {
static int gameSpeed = 10;
Ball ball = new Ball(this);
private void move() {
ball.move();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
ball.paint(g2d);
}
public static void main(String args[]) throws InterruptedException {
JFrame frame = new JFrame("Pong");
Main game = new Main();
frame.add(game);
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true) {
game.move();
game.repaint();
Thread.sleep(gameSpeed);
}
}
}
And here's the actual Ball
class, which handles movement conditions. 这是实际的
Ball
类,它处理运动条件。
package pong;
import javax.swing.*;
import java.awt.*;
public class Ball extends JPanel {
int x = 1;
int y = 1;
int dx = 1;
int dy = 1;
private Main game;
public Ball(Main game) {
this.game = game;
}
void move() {
System.out.println(getWidth() + getHeight());
if (x + dx < 0) {
dx = 1;
}
if (y + dy < 0) {
dy = 1;
}
if (x + dx > (getWidth() - 30)) {
dx = -1;
}
if (y + dy > (getHeight() - 30)) {
dy = -1;
}
x = x + dx;
y = y + dy;
}
public void paint(Graphics2D g) {
g.fillOval(x, y, 30, 30);
}
}
EDIT: Problem solved, I simply didn't tell getWidth() and getHeight() what to refer to. 编辑:问题解决了,我只是没有告诉getWidth()和getHeight()引用什么。 Obviously, if I don't tell them what to get, they'll return null.
显然,如果我不告诉他们要得到什么,他们将返回null。 Derp.
DERP。 The simple fix was to change them to game.getWidth() and game.getHeight().
简单的解决方法是将它们更改为game.getWidth()和game.getHeight()。 Thanks for the help, though!
谢谢你的帮助! All your inputs help in other areas as well.
您的所有输入也有助于其他领域。 :)
:)
Graphics
/ Java2D
by default never returs reasonable Dimension
, result is zero Dimension
, you have to override getPreferredSize
for JPanel
, then getWidth/Height
will return correct coordinates for JPanels' size. 默认情况下,
Graphics
/ Java2D
永远不会返回合理的Dimension
,结果为零Dimension
,您必须为JPanel
覆盖getPreferredSize
,然后getWidth/Height
将返回JPanels大小的正确坐标。
then to use JFrame.pack()
instead of any sizing. 然后使用
JFrame.pack()
而不是任何大小调整。
override paintComponent
for Swing JComponents
, instead of paint()
, inside paintComponent
1st. 在
paintComponent
1st中覆盖Swing JComponents
paintComponent
,而不是paint()
。 code line should be super.paintComponent
, otherwise painting cumulated. 代码行应该是
super.paintComponent
,否则绘制累积。
never to use Thread.sleep(int)
in Swing
, nor for Custom painting or animations in Java7 and Swing, use Swing Timer
instead endless loop stopped by Thread.sleep(int)
. 永远不要在
Swing
使用Thread.sleep(int)
,也不要在Java7和Swing中使用自定义绘制或动画,而是使用Swing Timer
而不是Thread.sleep(int)
停止的无限循环。
This is a complex issue made worse by some design decisions. 这是一个复杂的问题,由于某些设计决策而变得更糟。
Normally, Swing wants components to be used within the constraints a layout manager. 通常,Swing希望组件在布局管理器的约束内使用。 Layout managers require a certain amount of information in order to make decisions about how best layout these components.
布局管理器需要一定量的信息才能决定如何最好地布局这些组件。 This includes
getPreferred/Minimum/Maximum
size. 这包括
getPreferred/Minimum/Maximum
大小。
The problem you have is you don't actually want to use layout managers, as you want to position the Ball
manually. 您遇到的问题是您实际上并不想使用布局管理器,因为您想手动定位
Ball
。 When you throw out the layout manager, you become responsible for a lot of work, ensuring that the component is size and position correctly within the parent container. 当您抛弃布局管理器时,您将负责大量工作,确保组件在父容器中的大小和位置正确。
A simpler solution would be to generate a "game" surface onto which you can paint game elements or entities. 一个更简单的解决方案是生成一个“游戏”表面,您可以在其上绘制游戏元素或实体。
The problem is, you don't seem to know which approach you want to use. 问题是,您似乎不知道要使用哪种方法。 Your
Ball
extends from JPanel
, but your Main
panel is painting itself...this is not how components should be rendered. 你的
Ball
从JPanel
扩展,但你的Main
面板正在自己绘画......这不是组件应该如何渲染。
Instead of using components as a basis for game entities, which introduces numerous issues and management overhead, you could simply use Main
as the primary gaming surface and render all the entities to it directly. 而不是使用组件作为游戏实体的基础,这会引入许多问题和管理开销,您可以简单地使用
Main
作为主要游戏界面并直接渲染所有实体。 This gives you greater control and simplifies the process - IMHO 这为您提供了更好的控制并简化了流程 - 恕我直言
For example... 例如...
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main extends JPanel {
public static final int GAME_SPEED = 40;
Ball ball = new Ball();
protected void move() {
ball.move(this);
}
public Main() {
setLayout(null);
Timer timer = new Timer(GAME_SPEED, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
move();
repaint();
}
});
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
ball.paint((Graphics2D)g);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public static void main(String args[]) throws InterruptedException {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Pong");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Main game = new Main();
frame.add(game);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
public interface Entity {
public void paint(Graphics2D g2d);
public Rectangle getBounds();
}
public interface MovableEntity extends Entity {
public void move(Container parent);
}
public class Ball implements MovableEntity {
private int dx = 1;
private int dy = 1;
private int x;
private int y;
@Override
public void move(Container parent) {
int width = parent.getWidth();
int height = parent.getHeight();
int x = getX();
int y = getY();
x += dx;
y += dy;
if (x + dx < 0) {
dx = 1;
}
if (y + dy < 0) {
dy = 1;
}
if (x + dx > (width - getBounds().width)) {
dx = -1;
}
if (y + dy > (height - getBounds().height)) {
dy = -1;
}
setLocation(x, y);
}
@Override
public void paint(Graphics2D g2d) {
int width = getBounds().width;
int height = getBounds().height;
int dim = Math.min(width, height);
int xPos = x + ((width - dim) / 2);
int yPos = y + ((height - dim) / 2);
g2d.fillOval(xPos, yPos, dim, dim);
}
@Override
public Rectangle getBounds() {
return new Rectangle(x, y, 30, 30);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.