【问题标题】:Dynamically changing NSWindow's isMovableByWindowBackground and isMovable动态改变 NSWindow 的 isMovableByWindowBackground 和 isMovable
【发布时间】:2017-11-25 23:49:37
【问题描述】:

我一直在努力解决这个非常令人沮丧的问题,希望有人能提供帮助。我正在尝试创建一个具有多个视图的 NSWindow。这些视图可以相互重叠。这些是要求。

  • 下图中蓝色的 NSView 是可以移动窗口的。
  • 黄色的 NSView 无法移动窗口。这是蓝色 NSView 下方的另一个 NSView 实例。
  • 该运动需要与任何其他窗口运动一样。
  • 将窗口一直拖到顶部等操作应该会激活 Expose(Sierra 和 High Sierra)。

第一次尝试

我尝试了以下方法。不幸的是,这根本行不通。

在 NSWindow 中

override func awakeFromNib() {
    self.refreshElements()
    self.titlebarAppearsTransparent = true
    self.isMovableByWindowBackground = true
}

在我的自定义视图中

class Blue: NSView {
    public override var mouseDownCanMoveWindow: Bool { return true }
}

class Yellow: NSView {
    public override var mouseDownCanMoveWindow: Bool { return false }
}

第二次尝试

然后我尝试在蓝色中实现 mouseDown mouseDraggedmouseUp。我会计算窗口上的鼠标移动和self.setFrame(frameRect:display:animate:)。这工作正常,因为我可以控制移动窗口,但它有几个问题。一个不管是什么窗口的移动总是比较慢。我认为即使我将animate 属性设置为false,它也是动画。它也不会像其他窗口那样激活 Expose。


第三次尝试

这是我在一个主要问题上所能达到的最接近我想要的行为。初始 mouseDown 未注册。所以你不能点击蓝色视图并拖动和移动窗口。你有 mouseDown,mouseUp,然后 mouseDown 再次为了拖动移动窗口。

public class MyWindow: NSWindow {

    @IBOutlet var blue: NSView!
    @IBOutlet var yellow: NSView!

    public override func awakeFromNib() {
        self.titlebarAppearsTransparent = true
        self.isMovable = false
        self.isMovableByWindowBackground = true
    }

    public override func mouseDown(with event: NSEvent) {
        let point = event.locationInWindow

        let move = NSPointInRect(point, self.blue.frame)
        self.isMovableByWindowBackground = move
        self.isMovable = move

        super.mouseDown(with: event)
    }
    public override func mouseDragged(with event: NSEvent) {
        super.mouseDragged(with: event)
    }

}

我首选的方法是方法 3。它是最简洁的代码,除了必须单击然后再次单击以使事情正常工作的异常行为之外,其他一切都是完美的。我的问题是如何在动态设置为允许移动后强制初始点击也注册到窗口?

【问题讨论】:

    标签: cocoa


    【解决方案1】:

    从 macOS 10.11 开始,NSWindow 已经为此目的使用了方法 performDrag(with:)。它启动窗口拖动,就像用户单击并拖动标题栏时所做的一样。你的蓝色视图可以简单地调用它来覆盖mouseDown()

    mouseDownCanMoveWindow 的作用在于它只是将问题传递给超级视图。除非直到窗口的内容视图的所有祖先视图都返回 true,否则这无关紧要。

    【讨论】:

    • 我不敢相信我错过了。如果我能以某种方式给你一千张赞成票,我会的。
    猜你喜欢
    • 1970-01-01
    • 2016-09-07
    • 2015-07-17
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多