0

我有一个带有一个直接子级的 AWT 容器,并在索引 0 处添加一个新子级,使其可见,验证父 Frame 并重新绘制。(子类是扩展 Panel 的类,但这似乎无关紧要。)一切都很好,Container 包含 2 个直接子类,如预期的那样。

然后我通过隐藏它并从孩子那里调用Container.remove(this)来解雇孩子,然后验证并重新绘制容器。在 1.7 之前的所有以前的 JRE 上,这都可以正常工作,并且原始子项留在容器中。然而,在 1.7 上,remove(this)它也删除了原来的孩子,即它清空了 Container。调用Container.remove(0)具有相同的效果。有没有人知道如何解决这个问题?它看起来像一个可怕的 JVM 错误。

即 - 开始时:容器包含子 [A]。- 添加 B 后,Container 包含子项 [B,A]。- 调用 remove(this) 或 remove(0) 后,Container 不包含任何内容:[]。

虽然我可以在 之前检索原始子项remove(),然后add()将其返回,但这不可避免地会导致重大的重绘和不可接受的性能。

4

2 回答 2

2

我认为不是真的,我不能模拟这个问题,

Win7、JDK7_04在我这边

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

打印出

run:
 Components Count after Adds :2
 Components Count after Adds :3
 Components Count after Adds :4
 Components Count after Adds :5
 Components Count after Adds :6
 Components Count after Adds :7
 Components Count after Removes :6
 Components Count after Removes :5
 Components Count after Removes :4
 Components Count after Removes :3
 Components Count after Removes :2
 Components Count after Removes :1
BUILD SUCCESSFUL (total time: 2 minutes 14 seconds)

从代码

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;

public class AddComponentsAtRuntime {

    private JFrame f;
    private Container panel;
    private JCheckBox checkValidate, checkReValidate, checkRepaint, checkPack;

    public AddComponentsAtRuntime() {
        JButton b = new JButton();
        b.setBackground(Color.red);
        b.setBorder(new LineBorder(Color.black, 2));
        b.setPreferredSize(new Dimension(600, 10));
        panel = new Container();
        panel.setLayout(new GridLayout(0, 1));
        panel.add(b);
        f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(panel, "Center");
        f.add(getCheckBoxPanel(), "South");
        f.setLocation(200, 200);
        f.pack();
        f.setVisible(true);
    }

    private JPanel getCheckBoxPanel() {
        checkValidate = new JCheckBox("validate");
        checkValidate.setSelected(false);
        checkReValidate = new JCheckBox("revalidate");
        checkReValidate.setSelected(false);
        checkRepaint = new JCheckBox("repaint");
        checkRepaint.setSelected(false);
        checkPack = new JCheckBox("pack");
        checkPack.setSelected(false);
        JButton addComp = new JButton("Add New One");
        addComp.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JButton b = new JButton();
                b.setBackground(Color.red);
                b.setBorder(new LineBorder(Color.black, 2));
                b.setPreferredSize(new Dimension(600, 10));
                panel.add(b);
                makeChange();
                System.out.println(" Components Count after Adds :" + panel.getComponentCount());
            }
        });
        JButton removeComp = new JButton("Remove One");
        removeComp.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                int count = panel.getComponentCount();
                if (count > 0) {
                    panel.remove(0);
                }
                makeChange();
                System.out.println(" Components Count after Removes :" + panel.getComponentCount());
            }
        });
        JPanel panel2 = new JPanel();
        panel2.add(checkValidate);
        panel2.add(checkReValidate);
        panel2.add(checkRepaint);
        panel2.add(checkPack);
        panel2.add(addComp);
        panel2.add(removeComp);
        return panel2;
    }

    private void makeChange() {
        if (checkValidate.isSelected()) {
            panel.validate();
        }
        if (checkReValidate.isSelected()) {
            panel.revalidate();
        }
        if (checkRepaint.isSelected()) {
            panel.repaint();
        }
        if (checkPack.isSelected()) {
            f.pack();
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                AddComponentsAtRuntime makingChanges = new AddComponentsAtRuntime();
            }
        });
    }
}
于 2012-06-27T18:58:38.070 回答
0

可能会发生此异常,因为在移除组件时触发了事件,并且在此事件处理方法中您仍然引用组件。例如,当您在代码中删除某个位置(除了在 actionPeformed() 中)时,最后一个组件仍然会触发/执行事件 actionPerformed。但通常 actionPerformed() 方法包含对用户操作(用户单击组件上的某处)做出反应的代码。因此,当最后一个组件被删除时,在 actionPerformed() 中对组件的任何引用都会导致异常。

对此的解决方案是将代码从 actionPerformed() 移动到例如 mouseClicked() 或其他事件处理程序,具体取决于您想要执行的操作。

于 2013-01-12T15:20:42.743 回答