将移动对象添加到 JFrame

Add moving objects to JFrame

我正在创建一个 java 游戏。游戏中有英雄和泡泡。当我按下箭头键时,英雄应该移动,而泡泡应该有连续的对角线移动。当我将英雄或气泡分别直接添加到 JFrame 时,我得到了所需的行为,但是当我将它们都添加时,我只得到一个非常小的正方形!我尝试将它们添加到相同的 JPanel,然后将 JPanel 添加到 JFrame,但它不起作用。可能我必须为 JPanel 定义某种类型的布局。

我做错了什么?

代码:

public class Pang {
public static void main(String[] args) {

    JFrame f=new JFrame();
    JPanel gamePanel=new JPanel();
    gamePanel.setPreferredSize(new Dimension(800, 600));


    DrawHero d=new DrawHero();
    DrawBubble bubble=new DrawBubble();

    gamePanel.add(d);
    gamePanel.add(bubble);

    f.add(gamePanel);

    f.setVisible(true);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setSize(800, 600);
}
}


public class DrawHero extends JPanel implements ActionListener, KeyListener {
    Timer myTimer = new Timer(5, this);
    int x = 0, y = 0, dx = 0, dy = 0, step = 10;
    private transient Image imageHero = null;

    public DrawHero() {
        myTimer.start();
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);

    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;

        imageHero = getHeroImage();

        g2.drawImage(imageHero, x, y, 40, 40, null);

    }

    public Image getHeroImage() {
        Image image = null;

        image = getImage("hero.png");
        return image;
    }

    public Image getImage(String path) {
        Image tempImage = null;
        try {
            URL heroiURL = DrawHero.class.getResource(path);
            tempImage = Toolkit.getDefaultToolkit().getImage(heroiURL);
        } catch (Exception e) {
            System.out.println("Error loading hero image! - "
                    + e.getMessage());
        }
        return tempImage;
    }

    public void actionPerformed(ActionEvent e) {

        repaint();
    }

    public void moveUp() {

        y = y - step;

    }

    public void moveDown() {
        y = y + step;

    }

    public void moveLeft() {

        x = x - step;

    }

    public void moveRight() {
        x = x + step;

    }

    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_UP) {
            moveUp();
        }
        if (keyCode == KeyEvent.VK_DOWN) {
            moveDown();
        }
        if (keyCode == KeyEvent.VK_LEFT) {
            moveLeft();
        }
        if (keyCode == KeyEvent.VK_RIGHT) {
            moveRight();
        }
    }

    public void keyTyped(KeyEvent e) {
    }

    public void keyReleased(KeyEvent e) {
    }
}


public class DrawBubble extends JPanel implements ActionListener, KeyListener {
    Timer myTimer = new Timer(5, this);
    int x = 100, y = 200, dx = 0, dy = 0, step = 10;
    private transient Image imageHero = null;

    public DrawBubble() {
        myTimer.start();
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);

    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.fill(new Ellipse2D.Double(x, y, 40, 40));


    }


    public void actionPerformed(ActionEvent e) {

         x=x+dx;
         y=y+dy;
        repaint();
    }

    public void moveBubble() {
         dy=2;
         dx=2;
    }



    public void keyPressed(KeyEvent e) {
        moveBubble();

    }

    public void keyTyped(KeyEvent e) {
    }

    public void keyReleased(KeyEvent e) {
    }
}

When I add the hero or the bubble directly into to the JFrame separately I get the desired behavior, but when I add them both i just get a very small square!

JFrame 的默认布局管理器是 BorderLayout。当您在没有约束的情况下使用 add(component) 时,组件将转到 CENTER。 CENTER只能添加一个组件,所以只显示最后添加的一个。

I tried to add them to the same JPanel and after add that JPanel to the JFrame but it is not working.

JPanel 的默认布局管理器是遵循组件首选大小的 FlowLayout。问题是你没有重写 getPreferredSize() 方法,所以大小是 (0, 0) 并且没有什么可绘制的。

Probably I have to define some type of layout to the JPanels.

实际上,由于您想要随机运动,因此需要在面板上使用空布局,然后使用组件的 setSize()setLocation() 方法来定位组件。

那么当您执行此操作时,自定义绘制应始终在 (0, 0) 而不是 (x, y) 处完成,因为该位置将控制组件在面板上绘制的位置。

我建议 DrawHeroDrawBubble(应分别称为 HeroBubble)都不应扩展任何 JComponent。相反,每个人都应该知道如何在请求时将自己绘制到传递给它的 Graphics 对象。

然后单个 GameFieldPlayingArea class 应该保留对所有 Bubble 对象和 Hero 的引用并绘制调用 draw(Graphics) 那些对象的方法。

使用这种方法不必担心 GameField 组件内的布局(它们变得无关紧要)。

这是我在 this answer to [Collision detection with complex shapes 中渲染静止物体所追求的基本策略。