2012-06-27 63 views
0

我有一個AWT容器有一個直接的孩子,並添加一個新的孩子在索引0,使其可見,驗證父框架和重繪。 (孩子是擴展Panel的類,但看起來並不相關)。一切都很好,並且容器按預期包含2個直接孩子。Java 7的bug Container.remove()刪除所有組件

然後,我隱瞞孩子並從孩子那裏調用Container.remove(this),然後驗證和重新繪製容器,從而解僱孩子。在1.7之前的所有以前的JRE中,這工作正常,並且原始的孩子留在容器中。然而,在1.7上,remove(this)也移除了原始的孩子,即它清空了容器。撥打Container.remove(0)具有同樣的效果。有沒有人有任何想法如何解決這個問題?它看起來像一個可怕的JVM錯誤。

即 - 開始時:Container包含子[A]。 - 添加B後,Container包含子[B,A]。 - 在調用remove(this)或remove(0)之後,Container不包含任何內容:[]。

雖然我可以在remove()之前找回原來的孩子,然後add()它回來,這不可避免地會導致重大重繪和不可接受的性能。

+3

你看過Java錯誤報告,看看是否有報告?你可以發佈一個小測試程序來顯示這個問題嗎?如果其他人在這裏驗證,那麼也許應該報告它是否尚未完成。 –

+0

儘管可能,但你碰到一個可怕的JVM錯誤是不太可能的。請發佈我們一些代碼來驗證您的聲明。 –

回答

2

我覺得不是真的,我不能來模擬這個問題,

的Win7,JDK7_04在我身邊

enter image description here

enter image description here

enter image description here

打印

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(); 
      } 
     }); 
    } 
} 
+0

我的代碼是純AWT:它根本不使用Swing。 – user1486577

+0

和最新的區別,任何更改? – mKorbel

0

此異常可能會發生,因爲當一個組件被刪除時觸發事件,並在你仍引用組件此事件處理方法。 例如,當您在代碼中刪除某處(除了actionPeformed())之外,最後一個組件仍然是事件actionPerformed將被觸發/執行。但是actionPerformed()方法經常包含對用戶操作作出反應的代碼(用戶在組件上的某個地方單擊)。因此,當最後一個組件被刪除時,對actionPerformed()中的組件的任何引用都將導致異常。

解決方法是將代碼從actionPerformed()移動到例如mouseClicked()或另一個事件處理程序,具體取決於你想要做什麼。