JPanel只显示一个对象

时间:2015-02-25 21:34:23

标签: java swing jframe jpanel

我已经从我的Ball类中制作了20个物体,因为我需要在屏幕上弹跳20个球,但是现在它只显示了1个球弹跳。 我认为这与添加的20个JPanels有关,它们相互重叠,但我并不完全确定。

  package com.company;

import javax.swing.*;
import java.awt.*;
import java.util.Random;
/**
 * Created by John on 25/02/2015.
 */
public class Ball extends JComponent{
    int _speedX;
    int _speedY;
    int _size;
    int _x;
    int _y;
    Color _color;
    int _windowX;
    int _windowY;

    Ball(int x, int y, int sz, int sX, int sY, Color c, int windowX, int windowY){
        _x = x;
        _y = y;
        _speedX = sX;
        _speedY = sY;
        _size = sz;
        _color = c;
        _windowX = windowX;
        _windowY = windowY;
        setForeground(_color);
    }

    public void update(){

            _x = _x + _speedX;
            _y = _y + _speedY;

            if (_x<0 || _x>_windowX-_size){
                _speedX*=-1;
            }

            if (_y<=0 || _y>_windowY-_size){
                _speedY*=-1;
            }



            this.repaint();


    }

    public static int randInt(int min, int max) {

        // NOTE: Usually this should be a field rather than a method
        // variable so that it is not re-seeded every call.
        Random rand = new Random();

        // nextInt is normally exclusive of the top value,
        // so add 1 to make it inclusive
        int randomNum = rand.nextInt((max - min) + 1) + min;
        return randomNum;
    }

    public void paint(Graphics g) {

        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.fillOval(_x, _y, _size, _size);
    }

    public static void main(String[] args) {
        // write your code here

        JFrame frame = new JFrame("Title"); //create a new window and set title on window
        frame.setSize(600, 600); //set size of window
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //set the window to close when the cross in the corner is pressed
        frame.setVisible(true); //make the window visible
        JPanel panel = new JPanel();
        frame.add(panel);

        Ball[] balls = new Ball[20];

        for(int i = 0; i<20;i++){

            balls[i] = new Ball(randInt(0,600),randInt(0,600),randInt(10,20),randInt(1,8), randInt(1,8),Color.yellow,600,600);
            panel.add(balls[i]);

        }



    while(true){

        for(int i = 0; i < balls.length; i++) {
            balls[i].update();

        }
        panel.repaint();
        try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); }
    }

}

}

2 个答案:

答案 0 :(得分:3)

建议:

  • 不要使Ball扩展JComponent或JPanel,而是使其成为逻辑非组件类。
  • 创建一个Drawing类,该类扩展JPanel并使用其paintComponent方法绘制,而不是其paint(...)方法。这将使动画更加流畅。
  • 通过遍历列表,创建一个ArrayList<Ball>个Ball对象,并在paintComponent(...)方法覆盖中绘制它们。
  • 同样移动名单所持的球。
  • 使用Swing Timer来驱动动画,而不是while (true)循环。如果你使用该循环犯了一个错误,你将冻结你的GUI,使其无法运行,因此Swing Timer是一种更安全的方法。

答案 1 :(得分:2)

  

它只显示1个球在弹跳。

我甚至看到一个我很惊讶。你不应该看到任何。

  

我认为这与添加的20个JPanels有关,它们相互重叠,

问题是默认情况下JPanel使用FlowLayout。向面板添加组件时,面板将遵循组件的首选大小。您使用的是自定义组件,默认大小为(0,0),因为您没有提供。

如果您想通过使用自定义组件继续此方法,则需要:

  1. 使用组件的属性来控制面板上组件的大小和位置。也就是说,您可以使用setSize(...)方法和setLocation(...)方法。您不需要_x,_y和_size变量。您也不需要颜色变量,因为您可以使用setForeground(...)来设置组件的颜色。

  2. 重写getPreferredSize()方法以返回球的大小。

  3. 覆盖'paintComponent(...)`方法以x / y值为0填充椭圆,因为绘画需要相对于球而不是面板进行。

  4. update()方法中,您使用setLocation(...)方法设置面板上组件的位置。

  5. 现在您还需要在面板上使用空布局,以便球可以随机移动。

    我不推荐这种方法用于最终解决方案,但实现此逻辑以了解如何创建自定义组件以及如何在此组件上完成绘制是一个很好的练习。理解这个概念将有助于您更好地理解Swing的工作原理。