2016-08-15 136 views
0

我一直在使用GUI,但發現了一個問題。大約10%的時間啓動該程序,我得到一個ClassCastException,但代碼不會掛起並且不會執行奇怪。它只是正常運行。什麼是weirder是堆棧跟蹤從不參考我寫的任何代碼。我試圖通過將所有內容都包含在try-catch中來證實這一點,並且確信,錯誤仍然被拋出並且從未被捕獲。由於它從來沒有真正影響代碼,我想這不會造成任何傷害,但我仍然寧願不發佈有我不瞭解的錯誤的代碼。爲什麼會拋出ClassCastException?

這裏是簡化的,因爲我可以得到它仍重複錯誤代碼:

import java.awt.GridBagLayout; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 

public class ErrorTracker extends JFrame{ 

    private JButton addRow; 
    private JScrollPane pane; 
    private JPanel scrollPanel, panel; 
    private JFrame frame; 

    public static void main (String[] args) { 
     /** 
     * The error only occurs sometimes, so I'm running it 20 times to 
     * make the odds of repeating the error pretty good. 
     */ 
     for(int i = 0; i < 20; i++) 
      new ErrorTracker(); 
    } 

    public ErrorTracker() { 
     /** 
     * Proof that the error somehow occurs outside of all the code... 
     * The line "An error took place" is never outputted. 
     **/ 
     try { 
      initialize(); 
     } catch (Exception e) { 
      System.out.println("An error took place"); 
     } 
    } 

    public void initialize() { 
     frame = new JFrame("Apparently this is defective"); 

     JPanel bigPanel = new JPanel(new GridBagLayout()); 

     frame.add(bigPanel); 

     addRow = new JButton("..."); 

     scrollPanel = new JPanel(); 
     scrollPanel.add(addRow); 

     pane = new JScrollPane(scrollPanel); 
     bigPanel.add(pane); 

     frame.setVisible(true); 

     panel = new JPanel(); 
     panel.add(addRow); 
    } 
} 

我知道有99%的把握,加入addRow兩次至少一些這樣做的原因,因爲服用輸出add(addRow)行中的任一行都可以解決問題。在任何人建議改變之前,別擔心。我會。但是,這個問題主要是爲了解這個錯誤發生的原因。擺脫frame.setVisible(true);也消除了這個問題,所以我想象當GUI被繪製時,它在自己的Thread中完成,它真的很生氣,因爲它將相同的元素添加到兩個JPanel s(這可以解釋爲什麼我的代碼不是在堆棧跟蹤中,我認爲...),但我不明白這個過程足夠好,不能確定地知道。

這裏的堆棧跟蹤:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException 
    at javax.swing.LayoutComparator.compare(Unknown Source) 
    at javax.swing.LayoutComparator.compare(Unknown Source) 
    at java.util.TimSort.countRunAndMakeAscending(Unknown Source) 
    at java.util.TimSort.sort(Unknown Source) 
    at java.util.Arrays.sort(Unknown Source) 
    at java.util.ArrayList.sort(Unknown Source) 
    at java.util.Collections.sort(Unknown Source) 
    at javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(Unknown Source) 
    at javax.swing.SortingFocusTraversalPolicy.getFocusTraversalCycle(Unknown Source) 
    at javax.swing.SortingFocusTraversalPolicy.getFirstComponent(Unknown Source) 
    at javax.swing.LayoutFocusTraversalPolicy.getFirstComponent(Unknown Source) 
    at javax.swing.SortingFocusTraversalPolicy.getDefaultComponent(Unknown Source) 
    at java.awt.FocusTraversalPolicy.getInitialComponent(Unknown Source) 
    at java.awt.Window.getMostRecentFocusOwner(Unknown Source) 
    at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source) 
    at java.awt.Component.dispatchEventImpl(Unknown Source) 
    at java.awt.Container.dispatchEventImpl(Unknown Source) 
    at java.awt.Window.dispatchEventImpl(Unknown Source) 
    at java.awt.Component.dispatchEvent(Unknown Source) 
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
    at java.awt.EventQueue.access$500(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue$4.run(Unknown Source) 
    at java.awt.EventQueue$4.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.SequencedEvent.dispatch(Unknown Source) 
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
    at java.awt.EventQueue.access$500(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue$4.run(Unknown Source) 
    at java.awt.EventQueue$4.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.run(Unknown Source) 

有誰知道爲什麼被拋出這個錯誤?我在另一個線程中是否正確,如果沒有,爲什麼堆棧跟蹤不會引用我的代碼?另外,它爲什麼只在某些時候拋出錯誤?

+0

您的類擴展了'JFrame'。不需要私人成員「框架」。 – pzaenger

+1

這是錯誤嗎? http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8013775 – khelwood

+0

@ khelwood我認爲這是錯誤!這是否意味着發生這種情況,因爲在我的主線程中使用Swing線程正在使用的組件的'addRow'可見的混亂之後,向'JPanel'添加'addRow'?我會繼續點擊「解決了我的問題」這個副本,但我很樂意確保我完全掌握了第一個 –

回答

0

首先你猜對了,問題是因爲你添加了兩次addRow。偶然地,第二次添加的面板不會顯示在框架中。 Swing中的組件必須只有一個父對象,它不能在同一時間給予兩個父對象。如果您想更改組件的父項,則必須先將其從其父項中刪除,然後將其添加到其他項中,然後使雙親無效以查看結果。

類拋出的異常發生是因爲父內部是混淆的

相關問題