マウスがアプレットのフレーム上を移動すると java.lang.ClassCastException が AWT イベントディスパッチスレッドからスローされる


症状

アプレットを Sun JRE を使用したブラウザで実行しているときに、マウスがアプレットのフレーム上を移動すると、ClassCastException が AWT イベントディスパッチスレッドからスローされます。同じアプレットが Microsoft VM では実行できます。

        java.lang.ClassCastException: sun.plugin....
         at MyApplet.mouseExit(Unknown Source)
         at java.awt.Component.handleEvent(Unknown Source)
         at java.awt.Component.postEvent(Unknown Source)
         at java.awt.Component.dispatchEventImpl(Unknown Source)
         at java.awt.Container.dispatchEventImpl(Unknown Source)
         at java.awt.Component.dispatchEvent(Unknown Source)
         at java.awt.EventQueue.dispatchEvent(Unknown Source)
         at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
         at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
         at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
         at java.awt.EventDispatchThread.run(Unknown Source)

原因

この例外には、考えられる原因が 2 つあります。

  1. フレーム上のマウスイベントを追跡するために、アプレットではフレームに MouseListener を登録しようとします。Microsoft VM の実装では、AWT 階層コンポーネントツリーアプレットにおけるアプレットの直接の親はフレームです。これは実装固有であり、変更される可能性があるにも関わらず、コードで依存しているアプレットがあります。

    public void foo()
    {
            Frame f = (Frame) getParent();
            ....
    }

     
    Sun JRE ではアプレットとフレームの間に別のコンテナがあるため、getParent()Frame オブジェクトを返さず、上記のコードでは ClassCastException がスローされます。
     
  2. Microsoft VM の実装では、java.applet.AppletContext はアプレットのフレームで実装されています。これは実装固有であり、変更される可能性があるにも関わらず、コードで依存しているアプレットがあります。

    public void foo()
    {
            Frame f = (Frame) getParent();
            ....
            AppletContext ac = (AppletContext) f;
            ....
    }

    Sun JRE では別のオブジェクトを使用して AppletContext を実装しているため、上記のコードでは ClassCastException がスローされます。

解決方法

最初の例を回避するには、包含関係の特定のレベルにおけるフレームに依存するのではなく、AWT 階層コンポーネントツリー全体をアプレットから移動してフレームの位置を特定します。

public void foo()
{
      // Navigate component tree
      Container c = getParent();
      while (c != null && (c instanceof Frame) == false)
              c = c.getParent();

      // Cast Container to Frame
      if (c instanceof Frame)
      {
          Frame f = (Frame) c;
               ...
      }
}

2 番目の例を回避するには、Applet.getAppletContext() メソッドを使用して AppletContext にアクセスします。

        public void foo()
    {
         ....
         AppletContext ac = (AppletContext) getAppletContext();
         ...
    }

 

詳細情報

        なし