问题
My JComponents aren't showing up on my JPanel for some reason.
Here's my code:
MAIN CLASS
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
// Main Class - executes the game
public class Main extends JFrame
{
public static int WIDTH = 800, HEIGHT = 800;
private JPanel jp;
private Dimension d;
private Snake s;
private Food f;
public Main()
{
setTitle("Snake");
setSize(WIDTH, HEIGHT);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
d = new Dimension(WIDTH, HEIGHT);
jp = new JPanel();
jp.setBackground(Color.GRAY);
jp.setPreferredSize(d);
getContentPane().add(jp);
// adds the snake
s = new Snake();
jp.add(s);
// adds food
f = new Food();
jp.add(f);
}
@Override
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
}
public static void main(String args[])
{
new Main();
}
}
SNAKE CLASS
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import javax.swing.JComponent;
// Snake Class - creates the Snake object
public class Snake extends JComponent implements KeyListener
{
public ArrayList snakeList = new ArrayList();
public int snakeX, snakeY, snakeWidth, snakeHeight;
public Snake()
{
snakeX = 100;
snakeY = 100;
snakeWidth = 20;
snakeHeight = 20;
snakeList.add(1);
addKeyListener(this);
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.RED);
g2.fillRect(snakeX, snakeY, snakeWidth, snakeHeight);
}
@Override
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_W || e.getKeyCode() == KeyEvent.VK_UP)
{
snakeX += 10;
System.out.println("Up");
}
if(e.getKeyCode() == KeyEvent.VK_S || e.getKeyCode() == KeyEvent.VK_DOWN)
{
snakeX -= 10;
System.out.println("Down");
}
if(e.getKeyCode() == KeyEvent.VK_D || e.getKeyCode() == KeyEvent.VK_RIGHT)
{
snakeY += 10;
System.out.println("Right");
}
if(e.getKeyCode() == KeyEvent.VK_A || e.getKeyCode() == KeyEvent.VK_LEFT)
{
snakeY -= 10;
System.out.println("Left");
}
}
@Override
public void keyReleased(KeyEvent e)
{
}
@Override
public void keyTyped(KeyEvent e)
{}
}
FOOD CLASS
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JPanel;
// Food Class - the class that adds more Snake objects when collided with Snake
public class Food extends JComponent
{
private Random r = new Random();
public int foodX, foodY, foodWidth = 20, foodHeight = 20;
public Food()
{
foodX = 400;
foodY = 400;
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.YELLOW);
g2.fillRect(foodX, foodY, foodWidth, foodHeight);
}
}
As you can see, I have 3 classes: 2 JComponents and 1 JFrame (my main class).
The Main Class has a JPanel within it that is added to the JFrame, and then that JPanel adds both those two JComponents but for some reason the JComponents are not showing up when I execute even though I'm pretty sure I have everything done correctly.
If anyone knows why this is not working that'd be awesome. Thanks!
回答1:
Your Food JComponent's preferred size will be 0,0, and this is what size it will preferentially take. One simple solution is to either set its preferred size or override its getPreferredSize()
method, but I think that even if you do this you might expose a bigger problem with your program. I assume that you want to display your snake and your food together in the same screen space. If so, then you're program structure is wrong -- food and snake classes should not be component classes (e.g., shouldn't extend JPanel or JComponent) but rather should be logical classes. You should have only one JPanel for drawing that has its paintComponent overridden and that inside this method it paints your snakes and food.
A side bit: you're overriding your JFrame's paint method, a dangerous thing to do. Fortunately you're doing any harm in it currently, but its presence might tempt you later to draw in there. Don't. I recommend that you remove this method and the temptation. My own preference is to almost never extend JFrame as there is rarely a reason to do this, and risks from doing so.
Regarding your comments:
To make clear, you're saying to only have one paintComponent() in my Main
I don't know what your "Main" is. As I mentioned above, I would create one JPanel for painting, override its protected void paintComponent(Graphics g)
method, and then paint the Snake and Food within this method.
and not in either my Snake or Food class?
Correct. Snake and Food should not extend a Swing component and therefore should not override paintComponent. I would give them a public void draw(Graphics g)
method that is called in the above class's paintComponent method and that passes in the Graphics or Graphics2D object given from the JVM.
And also, I'll make my Main extend JPanel instead of JFrame. If that's the case, where do I create the Snake and Food Objects in my Main class?
These are details that will depend on your actual code. I'm confident that you'll figure this out.
And also, can I keep the keyListener in the Snake class or should I put it in the Main class?
I almost never use KeyListeners and instead favor Key Bindings. Look at my many posts on this subject, many with example code for more.
来源:https://stackoverflow.com/questions/40661014/jcomponents-are-not-showing-up-on-jpanel