2009-12-10 99 views
4

我已經實現了一個簡單的鼠標監聽器,只要鼠標進入組件(一個JPanel),背景顏色就會改變,只要鼠標離開,它就會恢復。這有一些問題:Java Swing:改變鼠標的背景顏色

  • 有時候鼠標移動這麼快的mouseExit事件不會觸發
  • 如果我的組件有孩子的,當鼠標移動到孩子的它觸發mouseExit
  • 如果我快速移動鼠標到孩子的,在的mouseenter事件不會觸發

我猜這是一個EA sy一個擺動老兵。對於如何解決這個問題,有任何的建議嗎?我很想不使用定時器等...

回答

6

如果我把鼠標移動到孩子的 迅速,MouseEnter事件不 解僱

我從來沒有見過這樣的事情發生,但如果它是一個問題,那麼你可以處理mouseMoved改爲重置背景。

如果我的組件有孩子的,當 鼠標移動到孩子的它觸發 的mouseExit

使用下面的測試,當你離開組件的邊界的代碼纔會執行​​:

public void mouseExited(MouseEvent e) 
{ 
    if (! getVisibleRect().contains(e.getPoint())) 
    { 
     setBackground(...); 
    } 
} 
+0

如果將指針從外部移動到包含的子項(使用鼠標偵聽器),則父容器上的鼠標偵聽器將不會被觸發。在邊界區域緩慢移動它,它會。 – 2009-12-10 17:42:10

+0

我已經使用了你的技術和湯姆霍金的混合。不幸的是,只有其中一個人可以得到正確的答案。謝謝大家。 – 2009-12-10 18:08:17

3

有許多解決方案:

  • 添加鼠標偵聽到子組件。也是容器偵聽器,添加和刪除偵聽器,因爲組件被添加和刪除。不幸的是,添加鼠標聽衆不滿起泡鼠標事件(可怕的設計)。
  • 在頂部添加一個玻璃窗格。這是非常醜陋的,事件的轉發總是會引起問題。
  • AWTEventListener添加到默認的Toolkit並過濾您感興趣的事件。不幸的是需要安全權限。
  • 推送自定義EventQueue並過濾事件。這需要一個安全權限,無論如何,將applet和WebStart/JNLP應用程序獲得該權限。
+0

我我已經嘗試了玻璃窗,但無濟於事。我可以將玻璃窗格應用於簡單的JPanel嗎?我以爲你只能將它應用於JFrames。 由於我有多個JPanels,我真的需要將玻璃板應用到他們中的每一個。 – 2009-12-10 16:20:02

0

我無法重現此行爲。請編輯您的問題以提供演示問題的簡短代碼示例。

當我創建一個JPanel並在其中放入內容時,當鼠標移動到JPanel的子組件上時,JPanel不會獲取mouseExit。我猜你已經添加了MouseListeners給孩子們。

+0

是的,你是對的。我試圖給孩子添加鼠標監聽器。 – 2009-12-10 16:30:23

1

試圖容器上各種辦法,都沒有成功後,我結束了使用定時器。這並沒有幫助我的容器包含已經需要鼠標偵聽器的元素。

計時器方法還意味着我可以在短時間內延遲更改。 (在我的情況,我將展示在一個樹節點(容器)額外的按鈕,以及改變背景。)

在一個的mouseEntered()在容器上,一個定時器創建(如果不是已經有),每260毫秒重複一次。在每次調用Timer時,都會確定鼠標是否在容器內。如果是這樣,它第一次發信號通知鼠標懸停。如果不是,則它表示非鼠標懸停並停止定時器。

在Scala中,這是如下,其中方法調用到出入境()編碼小鼠是否結束與否(其中具有相同值的多個調用就沒有影響):

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() 
    } 
    } 
... 
}