java - 在java Swing中检测重叠对象

标签 java swing animation jframe

我正在尝试制作一个程序,它有一个移动的球和一个它所在的平台。我也是java新手,我不知道如何检测两个 Swing 对象何时重叠。我在下面编写了代码,我想知道检测重叠对象的最佳方法是什么。

KeyDemo.java:

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;

    public class KeyDemo
    {
        public static void main(String[] args)
  {
  JFrame frame = new JFrame();
  JPanel panel = new JPanel();
  LayoutManager overlay = new OverlayLayout(panel);
  panel.setLayout(overlay);

  final int FRAME_WIDTH = 800;
  final int FRAME_HEIGHT = 600;

  frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
  frame.setTitle("Move the Ball");
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

   final WallComponent wc1 = new WallComponent(400, 400);
   final BallComponent bc = new BallComponent(400, 300);
   panel.add(wc1);
   panel.add(bc);
   frame.add(panel);

   KeyboardController kc = new KeyboardController(bc);
   frame.addKeyListener(kc);

  frame.setVisible(true);




  class AnimationListener implements ActionListener{
        public void actionPerformed(ActionEvent event){
           bc.tick();
           //wc1.checkOverlap(bc);
        }
    }

    ActionListener aListener = new AnimationListener();

    final Timer timer = new Timer(1, aListener);
    timer.start();

  }
 }

KeyboardController.java:

    import java.awt.*;
    import java.awt.event.*;

public class KeyboardController implements KeyListener
{
BallComponent bComp;

public KeyboardController(BallComponent t)
{
    bComp = t;
}

/** Handle the key pressed event from the text field. */
public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();
    if(keyCode == 38)
    {
        System.out.println("Pressed Up!");
        bComp.moveUp();
    }
    if(keyCode == 37)
    {
        System.out.println("Pressed Left!");
        bComp.moveLeft();
    }
    if(keyCode == 39)
    {
        System.out.println("Pressed Right!");
        bComp.moveRight();
    }
    if(keyCode == 40)
    {
        System.out.println("Pressed Down!");
        bComp.moveDown();
    }
}

/** Handle the key released event from the text field. */
public void keyReleased(KeyEvent e) {
    int keyCode = e.getKeyCode();
    if(keyCode == 38)
    {
        System.out.println("Released Up!");
        bComp.stopY();
    }
    if(keyCode == 37)
    {
        System.out.println("Released Left!");
        bComp.stopX();
    }
    if(keyCode == 39)
    {
        System.out.println("Released Right!");
        bComp.stopX();
    }
    if(keyCode == 40)
    {
        System.out.println("Pressed Down!");
        bComp.stopY();
    }    
}


public void keyTyped(KeyEvent e) {
}


   }

BallComponent.java:

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;

    public class BallComponent extends JComponent
    {
int xSpeed;
int ySpeed;
int x;
int y;

public BallComponent(int x, int y)
{
    super();
    this.x = x;
    this.y = y;
}

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

    Ellipse2D.Double ball = new Ellipse2D.Double(x-10,y-10,10,10);
    g2.setColor(Color.RED);
    g2.fill(ball);
    g2.draw(ball);
}

public void moveLeft()
{
    xSpeed=-1;
}
public void moveRight()
{
    xSpeed=1;
}
public void moveUp()
{
    ySpeed=-1;
}
public void moveDown()
{
    ySpeed=1;
}
public void tick()
{
    x=x+xSpeed;
    y=y+ySpeed;

    repaint();
}
public void stopY()
{
    ySpeed=0;
}
public void stopX()
{
    xSpeed=0;
}

   }

WallComponent.java:

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;

   public class WallComponent extends JComponent
   {
int x;
int y;

public WallComponent(int x, int y)
{
    super();
    this.x = x;
    this.y = y;
}

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

    Rectangle wall = new Rectangle(x-40,y-40,40,40);
    g2.setColor(Color.YELLOW);
    g2.fill(wall);
    g2.draw(wall);
}
public void checkOverlap(BallComponent bc){
    if (this.contains(bc.getLocation())){
        bc.stopY();
        bc.stopX();
    }
}
   }

最佳答案

所有 Swing 组件都有一个“边界”的概念。这是一个矩形区域,它们在其中“绘制”。

如果您正确控制大小和位置,您应该能够使用从调用 Component#getBounds 返回的 Rectanglecontains 方法。

所以你的checkOverlap方法可能看起来像......

public void checkOverlap(BallComponent bc){
    if (getBounds().intersects(bc.getBounds())){
        bc.stopY();
        bc.stopX();
    }
}

您还需要确保在执行任何自定义绘制之前调用 super.paintComponent,特别是在使用从 JComponent 扩展的组件时。这将确保 Graphics 上下文已准备好正确绘制...

已更新

存在一系列问题。基本上,您不是自己将组件放置在父容器中(这就是我认为您所做的),而是将每个组件放置到填充父容器中,并且只“绘制”对象......这使生活更加美好困难

相反,如果您要使用组件,我会使用 null 布局(甚至可能使用 JLayeredPane 作为父容器)。

然后我会更改组件的物理位置,例如......

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.OverlayLayout;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestGame {

    public static void main(String[] args) {
        new TestGame();
    }

    public TestGame() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                JPanel panel = new JPanel();
                panel.setLayout(null);

                final int FRAME_WIDTH = 800;
                final int FRAME_HEIGHT = 600;

                frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
                frame.setTitle("Move the Ball");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                final WallComponent wc1 = new WallComponent(400, 400);
                final BallComponent bc = new BallComponent(400, 300);
                panel.add(wc1);
                panel.add(bc);
                frame.add(panel);

                KeyboardController kc = new KeyboardController(bc);
                frame.addKeyListener(kc);

                frame.setVisible(true);

                class AnimationListener implements ActionListener {

                    public void actionPerformed(ActionEvent event) {
                        bc.tick();
                        wc1.checkOverlap(bc);
                    }
                }

                ActionListener aListener = new AnimationListener();

                final Timer timer = new Timer(1, aListener);
                timer.start();

            }
        });
    }

    public class KeyboardController implements KeyListener {

        BallComponent bComp;

        public KeyboardController(BallComponent t) {
            bComp = t;
        }

        /**
         * Handle the key pressed event from the text field.
         */
        public void keyPressed(KeyEvent e) {
            int keyCode = e.getKeyCode();
            if (keyCode == 38) {
                System.out.println("Pressed Up!");
                bComp.moveUp();
            }
            if (keyCode == 37) {
                System.out.println("Pressed Left!");
                bComp.moveLeft();
            }
            if (keyCode == 39) {
                System.out.println("Pressed Right!");
                bComp.moveRight();
            }
            if (keyCode == 40) {
                System.out.println("Pressed Down!");
                bComp.moveDown();
            }
        }

        /**
         * Handle the key released event from the text field.
         */
        public void keyReleased(KeyEvent e) {
            int keyCode = e.getKeyCode();
            if (keyCode == 38) {
                System.out.println("Released Up!");
                bComp.stopY();
            }
            if (keyCode == 37) {
                System.out.println("Released Left!");
                bComp.stopX();
            }
            if (keyCode == 39) {
                System.out.println("Released Right!");
                bComp.stopX();
            }
            if (keyCode == 40) {
                System.out.println("Pressed Down!");
                bComp.stopY();
            }
        }

        public void keyTyped(KeyEvent e) {
        }

    }

    public class BallComponent extends JComponent {

        int xSpeed;
        int ySpeed;

        public BallComponent(int x, int y) {
            super();
            setBounds(x, y, 10, 10);
        }

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

            Ellipse2D.Double ball = new Ellipse2D.Double(0, 0, 9, 9);
            g2.setColor(Color.RED);
            g2.fill(ball);
            g2.draw(ball);
        }

        public void moveLeft() {
            xSpeed = -1;
        }

        public void moveRight() {
            xSpeed = 1;
        }

        public void moveUp() {
            ySpeed = -1;
        }

        public void moveDown() {
            ySpeed = 1;
        }

        public void tick() {
            int x = getX() + xSpeed;
            int y = getY() + ySpeed;

            setLocation(x, y);

            repaint();
        }

        public void stopY() {
            ySpeed = 0;
        }

        public void stopX() {
            xSpeed = 0;
        }

    }

    public class WallComponent extends JComponent {

        public WallComponent(int x, int y) {
            super();
            setBounds(x, y, 40, 40);
        }

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

            Rectangle wall = new Rectangle(0, 0, 40, 40);
            g2.setColor(Color.YELLOW);
            g2.fill(wall);
            g2.draw(wall);
        }

        public void checkOverlap(BallComponent bc) {

            System.out.println(" me: " + getBounds());
            System.out.println("you: " + bc.getBounds());

            if (getBounds().intersects(bc.getBounds())) {
                bc.stopY();
                bc.stopX();
            }
        }
    }
}

现在,您可以使用“绘制”对象,但在这种情况下,我将拥有一个 BallWall 的虚拟概念,您可以在单个组件中绘制它们。这些对象需要提供有关其位置和大小的信息,您可以再次使用 Rectangle#intersects 进行检查...

关于java - 在java Swing中检测重叠对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19945564/

相关文章:

java - 翻转和旋转图像。仿射变换在 java 中无法正常工作

java - 从另一个 JFrame 刷新 Jlist

JavaScript 来控制图像动画?

javascript - Vue.js:转换动画在点击时不起作用

java - 如何在 selenium java 中捕获和导航 <a> 和 <span> 标签下的元素

java - 如何使用泛型返回泛型类的类类型?

java - 如何检查是否有任何线程在等待条件变量?

java - 如何使用免费软件对Java Web应用程序进行连续部署

java - 为什么 gridbag 约束不起作用

javascript - 如何在不直接粘贴代码的情况下访问 html 中的 SVG 元素(最好使用 CSS)?