3

スレッドを含む 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.util.Arrays.mergeSort(Arrays.java:1293) の javax.swing.LayoutComparator.compare(LayoutComparator.java:61) での java.lang.ClassCastException。 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) で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) で java.awt.Component.dispatchEvent(Component.java:4460) で.awt.EventQueue.dispatchEvent(EventQueue.java:599) で java.awt.SequencedEvent.dispatch(SequencedEvent.java:101) で java.awt.EventQueue.dispatchEvent(EventQueue.java:597) で java.awt.EventDispatchThread. java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) で java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) で java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) でawt.EventDispatchThread.run(EventDispatchThread.java:122)

ありがとうございました。ダニエル

4

3 に答える 3

4

Swing の EventDispatchThread 以外のスレッドで UI の変更を行うことは、お勧めしません。

UI がそれ自体 (およびレイアウトのもの) を再描画しようとしていて、別のスレッドを使用して同時に UI の一部を変更することで干渉していると想像してください。このような状況では、混乱が生じる可能性が非常に高くなります。

詳細については、Java チュートリアルのレッスン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)Runnable を後で実行するようにスケジュールします が、RunnableSwingUtilities.invokeAndWait(Runnnable)をスケジュールし、実行されるまで待機します。

于 2010-06-03T14:37:33.243 に答える
1

All updates to Swing components should be done on the Event Dispatch Thread (EDT).

In your Thread you attempt to pack() the dialog every second. This code is NOT executing on the EDT.

Try using a SwingUtilities.invokeLater(...) to do the pack().

Or maybe a SwingWorker should be used instead of the Thread. Read the section from the Swing tutorial on Concurrency for more information.

Or maybe even a better approach is to start a Swing Timer to schedule closing of the dialog. When the Timer fires the code is automatically executed on the EDT. The Swing tutorial also has a section on using Timers.

于 2010-06-03T14:25:21.297 に答える
0

イベント ディスパッチャ スレッド以外のスレッドからダイアログを起動しています。UI の作成/更新は、Swing のイベント ディスパッチャ スレッド内から行う必要があります。

試す:

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

注: UI が表示される (可視になる) 前の UI への更新は、イベント ディスパッチャ スレッドの外部から行うことができます。ただし、UI が表示されたら、変更は常にイベント ディスパッチ スレッド内から行う必要があります。

于 2010-06-03T16:16:54.570 に答える