在可滚动的看法困境的可可粉图画

时间:2016-01-19 11:49:39

标签: swift macos cocoa nsview nsscrollview

我在Swift工作的第一个OSX应用程序,我在一些Cocoa概念中迷失了。

我在NSScrollView中放置了一个自定义NSView。我在覆盖的drawRect函数中绘制复杂的图表。图表非常大,但NSScrollView可以滚动整个视图。

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

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

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

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

谢谢

1 个答案:

答案 0 :(得分:3)

如果您的自定义视图在绘图期间不需要“实时”,这意味着滚动不会更改视图的内容,那么您可以通过多种方式执行此操作。

通过了解视图何时滚动,我已经解决了这类问题。您可能想要查看的一件事是从滚动视图注册通知的自定义视图。具体来说是NSScrollViewWillStartLiveScrollNotification。当视图滚动时,您可以将自定义视图缓存到NSBitmapImageRep并改为绘制。之前我已经用非常复杂的视图完成了这项工作,而且效果非常好。

另一个可能更简单的事情是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
    }
}