2017-01-01 86 views
3

我目前正在使用Swift爲Mac製作幻燈片應用程序。在這個應用程序中,我想隱藏鼠標,而幻燈片正在運行,並且鼠標還沒有移動一段時間,就像在Quick Time Player中完成的一樣。將鼠標移動到Mac應用程序後不移動它

現在我已經嘗試了一系列使用NSCursor.hide()NSCursor.unhide()以及NSCursor.setHiddenUntilMouseMoves()的方法,但沒有很好用。

首先,我沒有讓它在我的主ViewController中調用mouseMoved函數,其次NSCursor.setHiddenUntilMouseMoves()似乎並不總是工作,即使我沒有觸及我的觸控板。在代碼更改幻燈片中的圖像後,我發現圖像被更改,但使用調試器時,它並不會停留在該行代碼上,而不會隱藏光標。

有人能告訴我一個如何使這個工作的一般方法嗎?我很確定這不是一件奇特的事情,有很多簡單的方法可以做到這一點。

以下是我已經試過:

import Cocoa 

class DiashowViewController: NSViewController { 

    enum DiashowState { 
     case playing 
     case paused 
     case stopped 
    } 

    var files: [URL]? 
    var diaTimer = Timer() 
    var diashowState: DiashowState = .stopped 

    var mouseTimer = Timer() 

    @IBOutlet weak var diaView: NSImageView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

    } 

    override var representedObject: Any? { 
     didSet { 
     // Update the view, if already loaded. 

     } 
    } 

    func playDiashow() { 
     if diashowState == .paused { 
      diaTimer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(self.changeDia), userInfo: nil, repeats: true) 
      diashowState = .playing 
      NSCursor.setHiddenUntilMouseMoves(true) 
     } 
    } 

    func playDiashow(withFiles files: [URL]) { 
     stopDiashow() 

     self.files = files 
     diashowState = .paused 

     playDiashow() 
     changeDia() 
    } 

    func pauseDiashow() { 
     if diashowState == .playing { 
      diaTimer.invalidate() 
      diashowState = .paused 
     } 
    } 

    override func mouseMoved(with event: NSEvent) { 
     print("MOUSE MOVED") 
    } 

    func stopDiashow() { 
     pauseDiashow() 
     diaView.image = nil 
     files = nil 
     diashowState = .stopped 
    } 

    func changeDia() { 
     if diashowState == .playing { 
      let i = Int(arc4random_uniform(UInt32(files!.count))) 
      let thisDiaURL = files![i] 
      let thisDia = NSImage(contentsOf: thisDiaURL) 
      thisDia?.size = NSSize(width: (thisDia?.representations.first?.pixelsWide)!, height: (thisDia?.representations.first?.pixelsHigh)!) 
      diaView.image = thisDia 
      NSCursor.setHiddenUntilMouseMoves(true) 
      print("HIDE MOUSE") 
     } 
    } 

} 

非常感謝提前!

+1

請粘貼你試過的代碼 – Alistra

+0

對不起,你去了! –

回答

2

要接收mouseMoved事件,你需要一個NSTrackingArea添加到視圖,你可能已經發現了setHiddenUntilMouseMoves設置爲單發,需要之後,這些狀態的鼠標移動到被重申。

而不是試圖解開你的代碼我做了一個演示項目,我設置了一個視圖和一個按鈕的窗口。視圖將顏色從紅色變爲綠色以顯示狀態。

enter image description here

class ViewController: NSViewController { 

    @IBOutlet weak var xview: NSView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     xview.wantsLayer = true 
    } 

    //1. 
    var isPresentingSlideshow = false 
    @IBAction func toggle(_ sender: Any) { 

     if(isPresentingSlideshow) { 
      isPresentingSlideshow = false 
      xview.layer?.backgroundColor = NSColor.green.cgColor 
      teardownTracking() 
     } 
     else { 
      isPresentingSlideshow = true 
      xview.layer?.backgroundColor = NSColor.red.cgColor 
      setupTracking() 
     } 
    } 

    //2. 
    var trackingArea:NSTrackingArea? 
    func setupTracking() { 
     let area = NSTrackingArea(rect: xview.bounds, options: [.activeAlways,.mouseEnteredAndExited,.mouseMoved,.inVisibleRect] , owner: self, userInfo: nil) 
     xview.addTrackingArea(area) 
     trackingArea = area 
    } 

    //3. 
    func teardownTracking() { 
     if let trackingArea = trackingArea { 
      xview.removeTrackingArea(trackingArea) 
      self.trackingArea = nil 
      NSCursor.setHiddenUntilMouseMoves(false) 
     } 
    } 

    //4. 
    var cursorHideState = false 
    override func mouseMoved(with event: NSEvent) { 
     super.mouseMoved(with: event) 

     if !cursorHideState { 
      cursorHideState = true 
      //5. 
      DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { 
       [weak self] in 
       if let _ = self?.trackingArea { 
        NSCursor.setHiddenUntilMouseMoves(true) 
        self?.cursorHideState = false 
       } 
      } 
     } 
    } 

} 

什麼這裏發生的。

  1. 簡單的切換動作可以在播放/不播放狀態之間進行切換,並可以在色彩狀態下進行反映。
  2. 在視圖中添加NSTrackingArea。所有者是該視圖控制器,因此它將收到mouseMoved:事件。需要選項.mouseMoved來設置。
  3. 當幻燈播放未播放時,從視圖中刪除跟蹤區域,並將setHiddenUntilMouseMoves設置爲false。
  4. mouseMoved:處理程序
  5. 只要跟蹤區域存在且尚未等待,setHiddenUntilMouseMoves在兩秒後設置爲真。請注意,對self的弱引用可防止可能的保留週期。

這並不完美,因爲您可能會發現光標在離開窗口後隱藏了一次,但應該讓您朝着正確的方向前進。

+0

非常感謝,這正是我一直在尋找的! 可以使用Timer而不是DispatchQueue嗎?還是有很好的理由在Timer上使用它? –

+0

你也可以在這裏使用計時器。我的偏好是DispatchQueue作爲保留語義是一個更清晰的國際海事組織。但對於他們自己:-) –

+0

我試過你的解決方案,它似乎工作奇妙,除了'setHiddenUntilMouseMoves'調用似乎不隱藏光標。我只偶爾看到光標被隱藏。我知道這個函數被調用,因爲程序在正確的時刻停下來放置一個斷點,而在它下面調用'print'right也會在正確的時間被調用。 有什麼想法? –