2017-01-01 2 views
3

В настоящее время я делаю приложение для слайд-шоу для Mac с помощью Swift. В этом приложении я хочу скрыть мышь, пока слайд-шоу запущено, и мышь не была перемещена какое-то время, очень похоже на то, что это делается в Quick Time Player, например.Скрыть мышь в приложении Mac после его перемещения

Теперь я попробовал кучу способов, используя NSCursor.hide() и NSCursor.unhide(), а также NSCursor.setHiddenUntilMouseMoves(), но без него все получилось.

Во-первых, мне не удалось заставить его вызвать функцию mouseMoved в моем основном ViewController, а во-вторых 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 или есть веская причина использовать его по таймеру? –

+0

Здесь вы также можете использовать таймер.Я предпочитаю DispatchQueue, поскольку семантика сохранения немного более ясная IMO. Но каждому из них свойственно :-) –

+0

Я пробовал ваше решение и, похоже, прекрасно работает, за исключением того, что вызов 'setHiddenUntilMouseMoves' не кажется спрятанным курсором. Я только время от времени вижу, что курсор скрыт. Я знаю, что функция вызывается, потому что программа останавливается в нужные моменты для точки останова, которую я на нее накладываю, и вызов 'print'right под ней также вызывается в нужное время. Любая идея? –

Смежные вопросы