4

マウスがコンポーネント(JPanel)に入るたびに背景色が変化し、マウスが離れるたびに元に戻る単純なマウスリスナーを実装しました。これにはいくつかの問題があります。

  • マウスの動きが速すぎて、mouseExitイベントが発生しない場合があります
  • コンポーネントに子がある場合、マウスが子に移動すると、mouseExitがトリガーされます
  • マウスを子にすばやく移動すると、mouseEnterイベントが発生しません

これはSwingのベテランにとって簡単なことだと思います。これを修正する方法について何か提案はありますか?タイマーなどは使いたくない…

4

4 に答える 4

6

マウスを子にすばやく移動すると、mouseEnterイベントが発生しません

これが発生するのを見たことがありませんが、問題がある場合は、代わりにmouseMovedを処理して背景をリセットできます。

コンポーネントに子がある場合、マウスが子に移動すると、mouseExitがトリガーされます

次のテストを使用すると、コンポーネントの境界を離れた場合にのみコードが実行されます。

public void mouseExited(MouseEvent e) 
{
    if (! getVisibleRect().contains(e.getPoint()) )
    {
        setBackground(...);
    }
}
于 2009-12-10T16:19:41.573 に答える
3

いくつかの解決策があります:

  • 子コンポーネントにマウスリスナーを追加します。また、コンポーネントが追加および削除されるときにリスナーを追加および削除するためのコンテナリスナー。残念ながら、マウスリスナーを追加すると、マウスイベントのバブリングが混乱します(恐ろしいデザイン)。
  • 上部にガラス板を追加します。これは非常に醜いものであり、イベントの転送は常に問題を引き起こします。
  • AWTEventListenerデフォルトにを追加し、Toolkit関心のあるイベントをフィルタリングします。残念ながら、これにはセキュリティ権限が必要です。
  • EventQueueカスタムイベントとフィルターイベントをプッシュします。これにはセキュリティ権限が必要です。アプレットを配置すると、WebStart/JNLPアプリケーションはとにかくその権限を取得します。
于 2009-12-10T16:16:52.227 に答える
1

コンテナでさまざまなアプローチを試した後、成功せず、タイマーを使用することになりました。私のコンテナに、すでにマウスリスナーが必要な要素が含まれていることは役に立ちませんでした。

タイマーアプローチはまた、私が変更を短時間遅らせることができることを意味しました。(私の場合、ツリーノード(コンテナ)に追加のボタンを表示し、背景を変更します。)

コンテナのmouseEntered()で、260ミリ秒ごとに繰り返されるタイマーが作成されます(まだ存在しない場合)。タイマーを呼び出すたびに、マウスがコンテナ内にあるかどうかが判別されます。もしそうなら、それは初めてマウスオーバーの合図をします。そうでない場合は、マウスオーバーしていないことを通知し、タイマーを停止します。

Scalaでは、これは次のようになります。ここで、entryExit()のメソッド呼び出しは、マウスが上にあるかどうかをエンコードします(同じ値を持つ複数の呼び出しは影響しません)。

abstract class MouseInterpreter(component: JComponent) extends MouseAdapter {
  ...
  private var mouseOverAction: () => Unit   = () => {}
  private var mouseOverTimer: Option[Timer] = None
  ...
  def entryExit(entered: Boolean) // this is an abstract method

  override def mouseEntered(e: MouseEvent) {
    if (mouseOverTimer.isEmpty) {
      val aTimer = new Timer(260, new ActionListener {
        def actionPerformed(e: ActionEvent) {
          mouseOverAction()
        }
      })
      mouseOverTimer = Some(aTimer)
      mouseOverAction = () => {
        mouseOverAction = () => {
          val point = MouseInfo.getPointerInfo.getLocation
          SwingUtilities.convertPointFromScreen(point, component)
          if (component.getVisibleRect.contains(point))
            entryExit(entered = true)
          else {
            entryExit(entered = false)
            aTimer.stop()
            mouseOverTimer = None
            mouseOverAction = () => {}
          }
        }
      }
      aTimer.setRepeats(true)
      aTimer.start()
    }
  }
...
}
于 2013-10-11T22:24:09.600 に答える
0

この動作を再現することはできません。質問を編集して、問題を示す短いコードサンプルを提供してください。

JPanelを作成して何かを入れると、マウスがJPanelの子コンポーネント上を移動したときに、JPanelがmouseExitを取得しません。子にMouseListenersを追加したと思います。

于 2009-12-10T16:19:16.520 に答える