Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 在不移动鼠标后,将其隐藏在Mac应用程序中_Swift_Macos_Cocoa_Appkit_Nscursor - Fatal编程技术网

Swift 在不移动鼠标后,将其隐藏在Mac应用程序中

Swift 在不移动鼠标后,将其隐藏在Mac应用程序中,swift,macos,cocoa,appkit,nscursor,Swift,Macos,Cocoa,Appkit,Nscursor,我目前正在使用Swift为Mac制作幻灯片应用程序。在这个应用程序中,我想在幻灯片播放时隐藏鼠标,并且鼠标已经有一段时间没有移动了,就像在Quick Time Player中一样 现在我已经尝试了很多方法使用NSCursor.hide()和NSCursor.unhide()以及NSCursor.sethiddenutillmousemoves(),但没有一种很有效 首先,我没能让它在我的主ViewController中调用mouseMoved函数,其次是NSCursor.setHiddenUnt

我目前正在使用Swift为Mac制作幻灯片应用程序。在这个应用程序中,我想在幻灯片播放时隐藏鼠标,并且鼠标已经有一段时间没有移动了,就像在Quick Time Player中一样

现在我已经尝试了很多方法使用
NSCursor.hide()
NSCursor.unhide()
以及
NSCursor.sethiddenutillmousemoves()
,但没有一种很有效

首先,我没能让它在我的主ViewController中调用mouseMoved函数,其次是
NSCursor.setHiddenUntillMouseMoves()
,即使我根本没碰过我的触控板,它似乎也不总是能工作。它就在更改幻灯片中图像的代码之后,我看到图像正在更改,但是使用调试器,当光标未隐藏时,它不会停止在代码行上

有人能告诉我一个如何让它工作的一般方法吗?我很确定这不是一件奇异的事情,而且有比我现在尝试的更简单的方法

以下是我尝试过的:

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
事件,您需要在视图中添加一个
NSTrackingArea
,正如您可能已经发现的那样,
SetHiddenUntillMouseMoves
设置是单发的,需要在该状态下移动鼠标后重新指定

我没有试图解开你的代码,而是做了一个演示项目,在那里我设置了一个带有视图和按钮的窗口。视图将颜色从红色更改为绿色以显示状态

这里发生的事情是

  • 简单的切换动作,在播放/不播放状态之间切换,并在颜色状态下反映该状态
  • NSTrackingArea
    添加到视图中。所有者是该视图控制器,因此它将接收
    mouseMoved:
    事件。设置此选项需要选项
    .mouseMoved
  • 当幻灯片放映未播放时,从视图中删除跟踪区域,并将
    sethiddenutillmousemoves
    设置为false
  • mouseMoved:
    处理程序
  • 只要跟踪区域存在且尚未等待,则两秒钟后将设置为真。请注意,
    self
    的弱引用阻止了可能的保留循环

  • 这并不完美,因为您可能会发现光标在离开窗口后隐藏了一次,但应该会让您朝着正确的方向前进

    请粘贴你所尝试的代码,好了!非常感谢,这正是我想要的!是否可以使用计时器而不是DispatchQueue,或者是否有充分的理由在计时器上使用它?这里也可以使用计时器。我更喜欢DispatchQueue,因为retain语义在我看来更清晰一些。但对于每个人来说,它们各自的语义:-)我已经尝试了您的解决方案,它似乎工作得很好,只是调用
    setHiddenutilMouseMoves
    似乎并没有隐藏光标。我只是偶尔看到光标被隐藏。我知道函数被调用是因为程序在我放在它上面的断点的正确时刻停止,并且它下面的
    print
    调用也会在正确的时间被调用。知道吗?我不知道。你确定你的鼠标在通话时没有移动吗?我的测试是将鼠标移到跟踪区域,然后放手等待。是的,我是。我和你一样测试它。我刚刚测试过,每次鼠标移动时都会打印一些东西,调用
    sethiddenutilmousemoves
    后肯定没有移动,但光标只有在非常罕见的情况下才会隐藏。我之前也遇到过类似的问题,每次幻灯片中的图片发生变化时,我都会隐藏光标。
    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
                    }
                }
            }
        }
    
    }