Java Swing:マウスの背景色を変更します
-
18-09-2019 - |
質問
マウスがコンポーネント(jPanel)に入るたびに背景色が変化するシンプルなマウスリスナーを実装し、マウスが去るたびに戻って戻ります。これにはいくつかの問題があります:
- マウスが非常に速く動くことがあります MouseExit イベントは解雇されません
- 私のコンポーネントが子供を持っている場合、マウスが子供に移動すると、 MouseExit
- マウスを子供にすばやく移動すると、 マウスエンター イベントは解雇されません
これはスイング退役軍人にとって簡単なものだと思います。これを修正する方法に関する提案はありますか?タイマーなどを使用しないでください...
解決
マウスを子供にすばやく移動すると、マウスエンターイベントが解雇されません
私はこれが起こるのを見たことがありませんが、それが問題であれば、代わりにマウスモーインブを処理して背景をリセットすることができます。
私のコンポーネントがチャイルドを持っている場合、マウスがチャイルドに移動すると、マウスエクシットがトリガーされます
次のテストを使用すると、コードはコンポーネントの範囲を残すときにのみ実行されます。
public void mouseExited(MouseEvent e)
{
if (! getVisibleRect().contains(e.getPoint()) )
{
setBackground(...);
}
}
他のヒント
多くの解決策があります:
- マウスリスナーを子供コンポーネントに追加します。コンテナリスナーも、コンポーネントが追加および削除されたときにリスナーを追加および削除するためのリスナーです。残念ながら、マウスのリスナーを追加すると、マウスイベントの泡立ちが動揺します(恐ろしいデザイン)。
- 上部にガラス板を加えます。これはugい強大であり、イベントの転送は常に問題を引き起こします。
- 追加します
AWTEventListener
デフォルトにToolkit
そして、あなたが興味を持っているイベントのためにフィルタリングします。これには、残念ながらセキュリティ許可が必要です。 - カスタムを押します
EventQueue
イベントをフィルタリングします。これには、セキュリティ許可が必要であり、アプレットとWebStart/JNLPアプリケーションをとにかく許可を取得します。
コンテナでさまざまなアプローチを試した後、成功せずに、私は タイマー. 。私のコンテナに、すでにマウスリスナーが必要な要素が含まれていたことは助けにはなりませんでした。
タイマーアプローチは、短時間変更を遅らせることもできることを意味しました。 (私の場合、ツリーノード(コンテナ)に追加のボタンを表示し、背景を変更します。)
aで mouseentered() コンテナの上、a タイマー 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()
}
}
...
}
この動作を再現できません。質問を編集して、問題を示す短いコードサンプルを提供してください。
JPanelを作成して何かを入れると、JPanelがJPANELの子コンポーネントをマウスが移動したときにJPANELはMouseExitを取得しません。私はあなたが子供たちにムーアリステナーを追加したと推測しています。