Java 将对象添加到JPanel

Java 将对象添加到JPanel,java,swing,jpanel,Java,Swing,Jpanel,我通常不这么做,我讨厌别人这么做。。。但是我发现我自己花了6个小时来找出我错的地方。 我把那些台词重写了十几遍,改变了几种方法,但仍然不知道哈克错了什么 问题如下: 点击[Add]按钮应在面板上添加额外的圆圈(从x=0,y=0开始-左上角) 当前仅加载第一个圆,其余圆加载到arrayList,但未加载到面板 有什么想法吗 控球: import javax.swing.*; import javax.swing.border.LineBorder; import java.awt.even

我通常不这么做,我讨厌别人这么做。。。但是我发现我自己花了6个小时来找出我错的地方。 我把那些台词重写了十几遍,改变了几种方法,但仍然不知道哈克错了什么

问题如下: 点击[Add]按钮应在面板上添加额外的圆圈(从x=0,y=0开始-左上角)

当前仅加载第一个圆,其余圆加载到arrayList,但未加载到面板

有什么想法吗

控球:

    import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.event.*;
import java.awt.*;
import java.util.ArrayList;

public class BallControl extends JPanel {
    private int delay = 10; // Create a timer with delay 1000 ms
    private Timer timer = new Timer(delay, new TimerListener());

    private ArrayList<Ball> balls = new ArrayList<Ball>();
    private JButton jbtSuspend = new JButton("Suspend");
    private JButton jbtResume = new JButton("Resume");
    private JButton jbtAdd = new JButton("Add");
    private JButton jbtRemove = new JButton("Remove");
    private JButton jbtDirection = new JButton("Direction");
    private JScrollBar jsbDelay = new JScrollBar();
    private JPanel jplBalls = new JPanel(new BorderLayout());

    public BallControl() { // Group buttons in a panel
        JPanel panel = new JPanel();
        panel.add(jbtSuspend);
        panel.add(jbtResume);
        panel.add(jbtAdd);
        panel.add(jbtRemove);
        panel.add(jbtDirection);

        balls.add(new Ball());
        // Add panel-ball and buttons to the panel
        jsbDelay.setOrientation(JScrollBar.HORIZONTAL);
        setDelay(jsbDelay.getMaximum());
        timer.setDelay(delay);

        jplBalls.setBorder(new LineBorder(Color.blue));
        jplBalls.setVisible(true);

        setLayout(new BorderLayout());
        add(jsbDelay, BorderLayout.NORTH);
        add(jplBalls, BorderLayout.CENTER);
        add(panel, BorderLayout.SOUTH);     
        timer.start();
        jplBalls.add(balls.get(balls.size()-1));

        // Register listeners
        jbtSuspend.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                timer.stop();
            }
        });
        jbtResume.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                timer.start();
            }
        });
        jbtAdd.addActionListener(new ActionListener() {     
            public void actionPerformed(ActionEvent e) {
                addNewBallToPanel();
                if(jbtRemove.isEnabled()==false)
                    jbtRemove.setEnabled(true);
            }
        });
        jbtRemove.addActionListener(new ActionListener() {      
            public void actionPerformed(ActionEvent e) {
                removeBallFromPanel();
                if (balls.size()==0)
                    jbtRemove.setEnabled(false);
            }
        });
        jbtDirection.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                for(Ball b : balls)
                    b.changeDirection();
            }
        });

        jsbDelay.addAdjustmentListener(new AdjustmentListener() {
            public void adjustmentValueChanged(AdjustmentEvent e) {
                setDelay(jsbDelay.getMaximum() - e.getValue());
                timer.setDelay(delay);
            }
        });
    }

    public void addNewBallToPanel(){
        balls.add(new Ball());
        jplBalls.add(balls.get(balls.size()-1));

    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        for (Ball b : balls){
            b.paintComponent(g);
        }
    }

    private class TimerListener implements ActionListener {
        /** Handle the action event */
        public void actionPerformed(ActionEvent e) {
            repaint();
        }
    }

    public void removeBallFromPanel(){
        jplBalls.remove(balls.get(balls.size()-1));
        balls.remove(balls.size()-1);
    }

    public void setDelay(int delay) {
        this.delay = delay;
    }
}

两次编辑似乎解决了这个问题:

控制

private JPanel jplBalls = new JPanel(null);
jplBalls.setOpaque(false);
在舞会上

if (x > getParent().getWidth() - radius)
    dx = -Math.abs(dx);

if (y > getParent().getHeight() - radius)
    dy = -Math.abs(dy);
但我建议你们用一个面板,用它的paintComponent方法从数组中画出球

现在,您已经从多个面板创建了一个三明治,它们彼此重叠


另一种方法是使球成为一个小部件,并更改它的坐标

两次编辑似乎解决了问题:

控制

private JPanel jplBalls = new JPanel(null);
jplBalls.setOpaque(false);
在舞会上

if (x > getParent().getWidth() - radius)
    dx = -Math.abs(dx);

if (y > getParent().getHeight() - radius)
    dy = -Math.abs(dy);
但我建议你们用一个面板,用它的paintComponent方法从数组中画出球

现在,您已经从多个面板创建了一个三明治,它们彼此重叠


另一种方法是使球成为一个小部件,并更改它的坐标

两次编辑似乎解决了问题:

控制

private JPanel jplBalls = new JPanel(null);
jplBalls.setOpaque(false);
在舞会上

if (x > getParent().getWidth() - radius)
    dx = -Math.abs(dx);

if (y > getParent().getHeight() - radius)
    dy = -Math.abs(dy);
但我建议你们用一个面板,用它的paintComponent方法从数组中画出球

现在,您已经从多个面板创建了一个三明治,它们彼此重叠


另一种方法是使球成为一个小部件,并更改它的坐标

两次编辑似乎解决了问题:

控制

private JPanel jplBalls = new JPanel(null);
jplBalls.setOpaque(false);
在舞会上

if (x > getParent().getWidth() - radius)
    dx = -Math.abs(dx);

if (y > getParent().getHeight() - radius)
    dy = -Math.abs(dy);
但我建议你们用一个面板,用它的paintComponent方法从数组中画出球

现在,您已经从多个面板创建了一个三明治,它们彼此重叠


另一种方法是使球成为一个小部件,并更改它的坐标

Swing组件使用布局管理器。您创建了带有边框布局的“球”面板。BorderLayout只能在中心显示单个组件,也就是添加所有球的位置

当您添加其他球时,您永远不会重新验证()面板,因此默认情况下,所有球的大小都为0,这意味着没有要绘制的内容。即使您重新验证了()面板,也只有最后一个添加了显示的面板,因为默认情况下,面板是不透明的,因此添加的最后一个球将在其他球的顶部进行绘制。因此,你的问题的简单答案是,你可能需要使球不不透明

但是,这仍然不是一个很好的设计,因为您可能会在面板中添加许多球,每个球的大小大约为(500300)。由于所有的球都是非不透明的,所以绘画系统需要做大量的工作来找到一个不透明的背景,在所有的球都被绘制之前,需要对其进行绘制

如果你想处理组件。然后,每个组件都应该是非不透明的,并且每个组件的大小只能是您正在绘制的实际椭圆形的大小。您需要使用空布局,以便可以在面板上随机定位每个球。然后,您需要设置每个球的大小/位置,以便可以正确地对其进行绘制

或者另一种方法是根本不使用组件,而是只保留ArrayList中每个球的信息,然后进行自定义绘制,只需迭代ArrayList即可绘制每个球


有关最后一种方法的示例,请查看中的
DrawOnComponent
示例。代码并不完全是您想要的,但是概念是相同的,只是您的用户将单击一个按钮来添加一个圆,而不是使用鼠标。

Swing组件使用布局管理器。您创建了带有边框布局的“球”面板。BorderLayout只能在中心显示单个组件,也就是添加所有球的位置

当您添加其他球时,您永远不会重新验证()面板,因此默认情况下,所有球的大小都为0,这意味着没有要绘制的内容。即使您重新验证了()面板,也只有最后一个添加了显示的面板,因为默认情况下,面板是不透明的,因此添加的最后一个球将在其他球的顶部进行绘制。因此,你的问题的简单答案是,你可能需要使球不不透明

但是,这仍然不是一个很好的设计,因为您可能会在面板中添加许多球,每个球的大小大约为(500300)。由于所有的球都是非不透明的,所以绘画系统需要做大量的工作来找到一个不透明的背景,在所有的球都被绘制之前,需要对其进行绘制

如果你想处理组件。然后,每个组件都应该是非不透明的,并且每个组件的大小只能是您正在绘制的实际椭圆形的大小。您需要使用空布局,以便可以在面板上随机定位每个球。然后,您需要设置每个球的大小/位置,以便可以正确地对其进行绘制

或者另一种方法是根本不使用组件,而是只保留ArrayList中每个球的信息,然后进行自定义绘制,只需迭代ArrayList即可绘制每个球


有关最后一种方法的示例,请查看中的
DrawOnComponent
示例。代码并不完全是您想要的,但是概念是相同的,只是您的用户将单击一个按钮来添加一个圆,而不是使用鼠标。

Swing组件使用布局管理器。您创建了带有边框布局的“球”面板。BorderLayout只能在中心显示单个组件,也就是添加所有球的位置

当您添加其他球时,您永远不会重新验证()面板,因此默认情况下,所有球的大小都为0,这意味着没有要绘制的内容。即使您重新验证了()面板,也只有最后一个pa