2010-06-03 46 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线程中完成。