简体   繁体   中英

Adding multiple JPanel extended components to a JFrame

I'm new to Java and I've recently been trying to make an Atari Breakout game. I managed to get the player moving and the ball to bounce but not at the same time in the JFrame (the component that was added the latest is the one that is being shown). I made two seperate classes for the player and the ball (both extending from JPanel) and I think that might be the problem, though I don't really know.

Anyway, this is the code for the player:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
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.Rectangle2D;
import javax.swing.JPanel;
import javax.swing.Timer;


public class Player extends JPanel implements ActionListener, KeyListener{
    Timer t = new Timer(5,this);
    int x=200,vel=0;
    boolean outOfBoundsR = true, outOfBoundsL = true;
    public Player(){
        t.start();
        addKeyListener(this);
        setFocusable(true);
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        Rectangle r= g2.getClipBounds();
        r.x = x;
        g2.setColor(Color.blue);
        g2.fill(new Rectangle2D.Double(r.getX(),350,100,5));
        if(r.getX()>385){
            vel=0;
            outOfBoundsR = false;
        }else if(r.getX()<0){
            vel=0;
            outOfBoundsL = false;
        }

    }
    public void actionPerformed(ActionEvent e){
        repaint();
        x+=vel;
    }
    public void right(){
        vel = 1;
    }
    public void left(){
        vel = -1;
    }
    public void keyPressed(KeyEvent e){
        int key = e.getKeyCode();
        if(key == KeyEvent.VK_RIGHT&&outOfBoundsR){
            outOfBoundsL=true;
            right();
        } else if(key == KeyEvent.VK_LEFT&&outOfBoundsL){
            outOfBoundsR=true;
            left();
        }

    }
    public void keyReleased(KeyEvent e) {vel = 0;}
    public void keyTyped(KeyEvent e) {}
}

This is the code for the ball:

 import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.KeyListener;
 import java.awt.geom.Ellipse2D;
 import java.awt.geom.Rectangle2D;
 import javax.print.attribute.standard.Media;
 import javax.swing.JPanel;
 import javax.swing.Timer;

public class Ball extends JPanel implements ActionListener{
    Timer t = new Timer(5,this);
    double velx = 0, vely = -1, x = 250, y = 330;

    public Ball(){
        t.start();
        setFocusable(true);
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        Rectangle r = g2.getClipBounds();
        r.x = (int) x;
        r.y = (int) y;
        g2.fill(new Ellipse2D.Double(r.getX(), r.getY(), 8, 8));
        if(r.getY() < 0 || r.getY() > 355){
            vely -= (vely*2);
        }else if(r.getX() < 0 || r.getX() > 480){
            velx -= (velx*2);
        }
    }

    public void actionPerformed(ActionEvent e) {
        repaint();
        x += velx;
        y += vely;
    }

}

And this is the code for the GUI:

import javax.swing.JFrame;

public class Gui extends JFrame{

    public static void main(String[] args) {

        JFrame f= new JFrame(); // the frame
        Ball b = new Ball();    // the ball
        Player p = new Player();// the player

        f.getContentPane().add(p);
        f.getContentPane().add(b);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(500,400);
        f.setVisible(true);
    }

}

Thanks in advance! (I know this was a bit long...)

I don't know how you want your Ball and Player objects to interact, but in your example f.getContentPane().add(...) translates to f.getContentPane().add(..., BorderLayout.CENTER) . Therefore, p is replaced by b in the subsequent call to add - the content pane of JFrame makes use of a BorderLayout by default.

Have a look at the Swing layout manager tutorial for more information.

I think that better way to do it is make player and ball as component and make next object which can be JPanel as a game. But your way should work too. Problem can be with chosen layout in your frame. I can suggest this changes for you.

   public static void main(String[] args) {

      JFrame f= new JFrame(); // the frame
      Ball b = new Ball();    // the ball
      Player p = new Player();// the player

      f.getContentPane().add(p, BorderLayout.CENTRE);
      f.getContentPane().add(b, BorderLayout.EAST);
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.setSize(500,400);
      f.setVisible(true);
   }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM