2010-06-03 104 views
3

我有一個帶有線程的JDialog。偶爾在創建對話框時給我一個ClassCastException(這意味着我可以有成功的,沒有例外),我不知道它應該發生在哪裏。帶JDialog和線程的ClassCastException

這裏是我的JDialog類的

public class ConfirmExitDialog extends JDialog implements Runnable, 
    ActionListener { 
private static final long serialVersionUID = -8762051370686039110L; 
private Thread dialogThread; 
private boolean running; 
private int result, count = 60; 
private HandleExit handleExit = null; 

// GUI 
private JOptionPane optionPane; 
private JLabel msgLabel = new JLabel(); 
private JButton btnYes; 
private JButton btnNo; 

private void updateLabelText() { 
    msgLabel.setText("<html>Ønsker du at afslutte dagens salg?<br>Programmet afslutter automatisk om " + count + " sekunder.</html>"); 
} 

public int getResult() { 
    return result; 
} 

public ConfirmExitDialog(Frame frame, HandleExit handleExit) { 
    super(frame, false); 
    this.handleExit = handleExit; 

    setTitle("Afslut dagens salg?"); 
    display(); 

    running = true; 
    if (dialogThread == null) { 
     dialogThread = new Thread(this, "ConfirmExitDialog"); 
     dialogThread.start(); 
    } 
    this.setModal(true); 
} 

public void close() { 
    if (dialogThread != null) 
     running = false; 
} 

private void display() { 
    setLayout(new BorderLayout()); 

    // Buttons 
    btnYes = new JButton("Ja"); 
    btnYes.addActionListener(this); 
    btnYes.setMnemonic('J'); 
    add(btnYes, BorderLayout.WEST); 
    btnNo = new JButton("Nej"); 
    btnNo.addActionListener(this); 
    btnNo.setMnemonic('N'); 
    add(btnNo, BorderLayout.EAST); 
    JButton[] buttons = { btnYes, btnNo }; 

    updateLabelText(); 
    optionPane = new JOptionPane(msgLabel, JOptionPane.QUESTION_MESSAGE, 
      JOptionPane.YES_NO_OPTION, null, buttons, buttons[0]); 
    setContentPane(optionPane); 

    setDefaultCloseOperation(DISPOSE_ON_CLOSE); 

    // Handle window closing correctly. 
    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); 
    addWindowListener(new WindowAdapter() { 
     public void windowClosing(WindowEvent we) { 
     /* 
     * Instead of directly closing the window, we're going to change the 
     * JOptionPane's value property. 
     */ 
     optionPane.setValue(new Integer(JOptionPane.CLOSED_OPTION)); 
     } 
    }); 

    pack(); 
    setVisible(true); 
} 

private void countDown() { 
    updateLabelText(); 
    count--; 
} 

@Override 
public void run() { 
    // TODO Auto-generated method stub 

    try { 
     display(); 
     while (running && count > 0) { 
      System.out.println("Countdown " + count); 
      pack(); 
      countDown(); 
      Thread.sleep(1000); 
     } 

     setVisible(false); 
     if (count == 0) 
      handleExit.closeApplication(true, true); 


    } catch (InterruptedException ie) { 
     // Thread stopped 
    } 
} 

@Override 
public void actionPerformed(ActionEvent event) { 
    Object src = event.getSource(); 

    if (src == btnYes) { 
     setVisible(false); 
     result = JOptionPane.YES_OPTION; 
     running = false; 
     handleExit.closeApplication(true, false); 
    } 
    if (src == btnNo) { 
     setVisible(false); 
     result = JOptionPane.NO_OPTION; 
     running = false; 

    } 
} 

}

這裏的例外投的一個片段:在線程 「AWT-EventQueue的 - 0」 java.lang.ClassCastException

異常在 javax.swing.LayoutComparator.compare(LayoutComparator.java:61) at java.util.Arrays.mergeSort( Arrays.java:1293) 在 java.util.Arrays.mergeSort(Arrays.java:1282) 在 java.util.Arrays.sort(Arrays.java:1210) 在 java.util.Collections.sort (Collections.java:159) 在 javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(SortingFocusTraversalPolicy.java:119) 在 javax.swing.SortingFocusTraversalPolicy.getFirstComponent(SortingFocusTraversalPolicy.java:434) 在 javax.swing.LayoutFocusTraversalPolicy。 getFirstComponent(LayoutFocusTraversalPolicy.java:148) at javax.swing.SortingFocusTraversalPolicy.getDefaultComponent(SortingFocusTraversalP olicy.java:511) 在 java.awt.FocusTraversalPolicy.getInitialComponent(FocusTraversalPolicy.java:152) 在 java.awt.Window.getMostRecentFocusOwner(Window.java:2131) 在 java.awt.DefaultKeyboardFocusManager.dispatchEvent (DefaultKeyboardFocusManager.java:629) 在 java.awt.Component.dispatchEventImpl(Component.java:4502) 在 java.awt.Container.dispatchEventImpl(Container.java:2099) 在 java.awt.Window中。 dispatchEventImpl(Window.java:2478) at java.awt.Component.dispatchEvent(Component.java:4460) at java.awt.EventQueue.dispatchEvent(EventQueue.java:599) 在 java.awt.SequencedEvent.dispatch(SequencedEvent.java:101) 在 java.awt.EventQueue.dispatchEvent(EventQueue.java:597) 在 java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) 在 java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) 在 java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pump活動(EventDispatchThread.java:161) 在 java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

謝謝。 Daniel

+0

我想我應該感到自豪的是,兩個人喜歡我的建議足以重複它。 – camickr 2010-06-03 20:38:08

回答

1

Swing組件的所有更新都應在Event Dispatch Thread(EDT)上完成。

在您的線程中,您嘗試每秒打包()對話框。該代碼不在EDT上執行。

嘗試使用SwingUtilities.invokeLater(...)來執行pack()。

或者應該使用SwingWorker來代替Thread。有關更多信息,請參閱Concurrency的Swing教程部分。

或者甚至更好的方法是啓動Swing Timer來安排關閉對話框。定時器啓動時,代碼在EDT上自動執行。 Swing教程也有關於使用定時器的部分。比Swing的EventDispatchThread其他線程

4

UI修改強烈反對,因爲它能夠而且將會導致奇怪的副作用(就像你所遇到的一個)。

Immagine用戶界面即將重新繪製自己(和佈局的東西),你只是通過使用另一個線程同時更改UI部分來干預。在這種情況下,很可能會出現混亂。

詳細信息請參考Java教程課程Concurrency in Swing

正確的方式來處理,這是有後臺線程做是不是UI相關的任何工作,並計劃在EventDispatchThread一個UI更新作業(這將在處理事件之間執行作業)。

實施例:

Thread t = new Thread() { 

     public void run() { 

      // do background work 

      SwingUtilities.invokeLater(new Runnable() { 

       public void run() { 
        // update UI parts 
       } 
      }); 
     } 
    }; 
    t.start(); 

SwingUtilities.invokeLater(Runnnable)將安排一個可運行以用於以後執行,而 SwingUtilities.invokeAndWait(Runnnable)將安排一個Runnable並等待,直到它已被執行。

0

您從除事件分派器線程以外的線程啓動對話框。任何UI創建/更新都應該來自Swing的事件分派器線程。

嘗試:

SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
     // show the UI here (display method in your logic?) 
    } 
}); 

注:任何更新的用戶界面之前,顯示真實它(可見光)可以從事件調度線程之外完成。 但是一旦顯示UI,任何更改都應該始終從Event Dispatch線程中完成。