2017-01-01 5 views
3

私は現在、Swiftを使ってMac用のスライドショーアプリケーションを作っています。このアプリケーションでは、スライドショーの実行中にマウスを隠しておき、マウスがしばらく動かされていないようにしたいと思っています。例えば、Quick Time Playerのようにします。Macアプリケーションを移動しないでマウスを隠す

今私はNSCursor.hide()NSCursor.unhide()NSCursor.setHiddenUntilMouseMoves()を使ってたくさんの方法を試しましたが、それほどうまくいきませんでした。

まず、メインのViewControllerでmouseMoved関数を呼び出さないようにしました.2番目に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") 
     } 
    } 

} 

事前にどうもありがとう! mouseMovedイベントを受信する

+1

試したコードを貼り付けてください。 – Alistra

+0

申し訳ありません、ありがとうございます! –

答えて

2

あなたはビューに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は、トラッキングエリアが存在し、まだ待機していない限り、2秒後にtrueに設定されます。 selfへの弱い参照は、ここで保持可能サイクルを防ぐことに注意してください。

カーソルがウィンドウを離れた後に一度隠れていることがわかりますが、正しい方向に進むはずです。

+0

ありがとう、それはまさに私が探していたものです! DispatchQueueの代わりにTimerを使用することができますか、それともTimerで使用する理由がありますか? –

+0

ここでもタイマーを使うことができます。保持セマンティクスは少し明確になっているので、私の好みはDispatchQueueです。しかし、それぞれ独自の:-) –

+0

私はあなたの解決策を試してみたが、 'setHiddenUntilMouseMoves'の呼び出しがカーソルを隠しているようであることを除いては、すばらしく動作するようです。カーソルが隠れていることがときどきしかありません。関数が呼び出されたことはわかっています。なぜなら、プログラムはブレークポイントの正しい瞬間に停止し、その下の 'print'rightの呼び出しも適切なタイミングで呼び出されるからです。 –

関連する問題