我有一个AWT容器,有一个直接的子节点,在索引0处添加一个新的子节点,使其可见,验证父框架并重新绘制。(子类是扩展Panel的类,但这似乎并不相关。)一切都很好,并且Container如预期的那样包含两个直接子对象。
然后,我将孩子隐藏起来,从孩子那里调用Container.remove(this),然后验证并重新绘制容器,从而消除了孩子。在1.7之前的所有JRE上,这都可以正常工作,并且原始子文件留在Container中。然而,在1.7版本中,remove(this)也删除了原始子容器,即清空容器。调用Container.remove(0)也有同样的效果。有没有人有办法解决这个问题?它看起来像是一个可怕的JVM错误。
例如-开始时:容器包含子A。-添加B之后,容器包含子B,A。-调用remove(this)或remove(0)后,Container不包含任何内容:[]。
虽然我可以在remove()之前检索原始子对象,然后再add()它,但这不可避免地会导致重大的重新绘制和不可接受的性能。
发布于 2012-06-28 02:58:38
我认为不是真的,我不能模拟这个问题,
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();
}
});
}
}发布于 2013-01-12 23:20:43
此异常可能发生,因为在移除组件时会触发一个事件,而在此事件处理方法中,您仍然引用组件。例如,当您删除代码中的某个地方(不是在actionPeformed()中)时,最后一个组件仍然是事件actionPerformed,它将被触发/执行。但通常actionPerformed()方法包含对用户操作(用户在组件上的某处单击)做出反应的代码。因此,当删除最后一个组件时,actionPerformed()中对组件的任何引用都将导致异常。
这个问题的解决方案是将代码从actionPerformed()移到mouseClicked()或其他事件处理程序中,这取决于您想要做什么。
https://stackoverflow.com/questions/11232907
复制相似问题