【问题标题】:JComponents are not showing up on JPanelJComponents 没有出现在 JPanel 上
【发布时间】:2016-11-18 05:15:34
【问题描述】:

由于某种原因,我的 JComponent 没有出现在我的 JPanel 上。

这是我的代码:

主类

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();
    }
}

蛇类

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)
    {}  
}

食品类

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);
    }
}

如您所见,我有 3 个类:2 个 JComponents 和 1 个 JFrame(我的主类)。

主类中有一个 JPanel,它被添加到 JFrame,然后 JPanel 添加了这两个 JComponent,但由于某种原因,即使我很确定我拥有所有东西,当我执行时 JComponent 也没有出现正确完成。

如果有人知道为什么这不起作用,那就太棒了。谢谢!

【问题讨论】:

    标签: java swing jframe jpanel jcomponent


    【解决方案1】:

    您的 Food JComponent 的首选大小将是 0,0,这是它优先采用的大小。一个简单的解决方案是设置其首选大小或覆盖其getPreferredSize() 方法,但我认为即使您这样做,您的程序也可能会出现更大的问题。我假设你想在同一个屏幕空间中同时显示你的蛇和食物。如果是这样,那么你的程序结构是错误的——食物和蛇类不应该是组件类(例如,不应该扩展 JPanel 或 JComponent),而应该是逻辑类。你应该只有一个用于绘制的 JPanel,它的paintComponent 被覆盖,并且在这个方法中它绘制你的蛇和食物。

    附带一点:您正在覆盖 JFrame 的绘制方法,这是一件危险的事情。幸运的是,您目前正在对它造成任何伤害,但它的存在可能会诱使您稍后将其吸引到那里。不。我建议你去掉这个方法和诱惑。我自己的偏好是几乎从不扩展 JFrame,因为很少有这样做的理由,这样做有风险。


    关于你的 cmets:

    为了清楚起见,你是说我的 Main 中只有一个 paintComponent()

    我不知道你的“主要”是什么。正如我上面提到的,我将创建一个用于绘画的 JPanel,覆盖其protected void paintComponent(Graphics g) 方法,然后在此方法中绘制 Snake 和 Food。

    而且不在我的 Snake 或 Food 课程中?

    正确。 Snake 和 Food 不应扩展 Swing 组件,因此不应覆盖paintComponent。我会给他们一个public void draw(Graphics g) 方法,该方法在上述类的paintComponent 方法中调用,并传入JVM 提供的Graphics 或Graphics2D 对象。

    另外,我将让我的 Main 扩展 JPanel 而不是 JFrame。如果是这种情况,我应该在哪里创建 Main 类中的 Snake 和 Food 对象?

    这些细节取决于您的实际代码。我相信你会解决这个问题的。

    另外,我可以将 keyListener 保留在 Snake 类中还是应该将它放在 Main 类中?

    我几乎从不使用 KeyListeners,而是喜欢 Key Bindings。看看我的many posts on this subject,其中许多带有示例代码以获取更多信息。

    【讨论】:

    • 感谢您的回答!为了清楚起见,您是说在我的 Main 中只有一个 paintComponent() 而不是在我的 Snake 或 Food 类中?而且,我会让我的 Main 扩展 JPanel 而不是 JFrame。如果是这种情况,我应该在哪里创建 Main 类中的 Snake 和 Food 对象?另外,我可以将 keyListener 保留在 Snake 类中还是应该将它放在 Main 类中?
    • 好的,非常感谢你!剩下的我会尝试独奏,看看效果如何!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    • 2016-02-26
    • 1970-01-01
    相关资源
    最近更新 更多