swift - Cocoa 绘制可 ScrollView 的困境

标签 swift macos cocoa nsview nsscrollview

我在 Swift 中开发我的第一个 OSX 应用程序,但我迷失在一些 Cocoa 概念中。

我在 NSScrollView 中放置了一个自定义 NSView。我在覆盖的 drawRect 函数中绘制了复杂的图表。图表相当大,但 NSScrollView 会滚动整个 View 。

我不满意的是,每次调用 drawRect 时我都会重新绘制整个图表,并且在滚动、调整大小时等时调用它的频率非常高。

绘制图表需要大量的计算,需要绘制大量的形状。每次调用 drawRect 时都这样做似乎是错误的。我知道我可以将绘图限制在可见/脏矩形内,但这会更加复杂并且需要更多计算。

有没有更好的方法来绘制这样一个可滚动的图表?最好是一次性绘制整个图表,而不用担心稍后重新绘制它。

我想在未来为我的图表添加一些交互(鼠标点击)。这可能是重要的信息。

谢谢

最佳答案

如果您的自定义 View 在绘制过程中不需要处于“事件”状态,这意味着滚动不会更改 View 的内容,那么您可以通过多种方式执行此操作。

我通过了解 View 何时滚动来解决此类问题。您可能想要查看的一件事是为来自 ScrollView 的通知注册您的自定义 View 。特别是 NSScrollViewWillStartLiveScrollNotification。当 View 滚动时,您可以将自定义 View 缓存到 NSBitmapImageRep 中并绘制它。我以前用一个非常复杂的 View 做过这个并且它工作得很好。

另外一个可能更简单的事情是 NSScrollView 的 scrollsDynamically 属性。

在 Swift 2 中,您可以使用以下内容来帮助

在你的awakeFromNib

NSNotificationCenter.defaultCenter().addObserver(self, selector: "startScrolling", name: NSScrollViewWillStartLiveScrollNotification, object: self.scrollView)

NSNotificationCenter.defaultCenter().addObserver(self, selector: "endScrolling", name: NSScrollViewDidEndLiveScrollNotification, object: self.scrollView)

然后

func startScrolling() {
    //viewRep is an NSBitmapImageRep variable in your class
    //create a bitmap representation of your view
    self.lockFocus()
    self.viewRep = NSBitmapImageRep(focusedViewRect: self.bounds)
    self.unlockFocus()

    //set a flag which draw rect uses to know to draw the bitmaprep
    //viewRep is a Bool variable in your class
    self.scrollingFlag = true
    self.needsDisplay = true
}

func endScrolling() {
    self.scrollingFlag = false
    self.needsDisplay = true
}

你的画法

override func drawRect(dirtyRect: NSRect) {
    if self.scrolling {
         self.viewRep.drawInRect(....) // you can draw the viewRep here
    }
    else {
         //your normal drawing code here
    }
}

关于swift - Cocoa 绘制可 ScrollView 的困境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34876058/

相关文章:

ios - swift 核心数据 : Inserting instances of an Entity related to other 2 entities

swift - 在 Swift 中使用 PresentViewController 传递变量

ios - 在圆形路径上为 CAShapeLayer 设置动画

objective-c - 使用 Sparkle 更新后,应用程序不再处于事件状态

macos - 在 Mac 终端应用程序中 move 选项卡的快捷方式?

objective-c - 创建不会阻止与其他窗口交互的工作表

ios - 当点击通知时,将 viewController 呈现在 rootViewController 上

java -version 告诉我 8 但 jdk 是 1.7 - OSX 10.9.x

objective-c - NSTextField 等待循环结束才更新

macos - 我可以通过编程判断 Spotlight 是否已启用吗?