6

Cocoa 的NSScrollView解释得非常糟糕。我希望这里有人知道这一切是怎么回事,并且可以节省我几秒钟的时间。

所以我有一个自定义的 NSView。我实现 -drawRect: 让它绘制一些东西,用颜色填充自己,等等。然后我有一个 NSScrollView 包装它(通过界面 Builder 设置)。

现在,内部自定义视图的大小必须大于适合外部滚动视图的大小——它才能滚动。我意识到这一点。我顺便配置了它,以便滚动视图调整到周围窗口的大小,但这无关紧要。

我重写了我的内部视图的 -frame 方法以返回一个大小至少为 1000x1000 的框架。

- (NSRect)frame {
    CGFloat w = 1000;
    CGFloat h = 1000;
    if (self.superview.bounds.size.width > w)
        w = self.superview.bounds.size.width;
    if (self.superview.bounds.size.height > h)
        h = self.superview.bounds.size.height;
    return NSMakeRect(0, 0, w, h);
}

这是结果,我很难解释:

  • 当滚动视图包围小于 1000x1000 的区域时,我可以滚动

  • 唯一用颜色填充的区域(即我的 -drawRect: 方法对它有任何影响)是

    • 与滚动视图的边界一样大
    • 位于(0,0。我使用翻转,所以它是左上角,滚动后它最终位于可见区域之外。
  • 位于这个无关矩形之外的可见区域根本不会被绘制。

除了这一点,我什么都不知道。似乎绘制的矩形被裁剪到滚动视图窗口中的位置、大小或其他东西——但它没有考虑滚动的“位置”。

应该指出的是,我真的不希望发生任何其他事情。我觉得我错过了一块,但找不到哪个。对不起,文字墙,但我现在无法更好地解释。我希望回答比问更容易。

问候和希望,

不是里克·阿斯特利

4

3 回答 3

3

覆盖是一个非常非常非常糟糕的主意-frame。有很多东西取决于具有正确值的实际实例变量。而是尝试将框架设置为您想要使用的框架,setFrame:如果幸运的话,这可能会解决您的所有问题......

于 2010-08-26T17:53:04.077 回答
2

我同意 Max 的警告,即您不应该覆盖 -frame。如果要约束设置的框架,请覆盖其设置器 ( -setFrame: ) 和指定的初始化程序 ( -initWithFrame: ) 并根据需要调整建议的框架。

关于您的整体问题,我想知道您的问题是否是概念性的。-drawRect: 的参数:(你被要求重绘的脏矩形)如果你正在绘制一些你可以在部分中增量重绘的东西(比如网格 - 任何与dirtyRect相交的网格块都可以重绘,其余的可以是有用的)忽略)。如果你正在做一些必须完全重绘的事情,你应该使用 [self bounds] 而不是在 drawRect 传递的脏矩形。

例如,如果您只有一个标准的渐变背景,则很难从dirtyRect 中分辨出要重绘渐变的哪一部分,而仅使用渐变重绘整个视图则非常容易,完全忽略dirtyRect。

您正确地假设只有滚动视图的剪辑矩形暴露的视图区域通常会在滚动时被要求重绘。还需要考虑与滚动视图的 -copiesOnScroll 的交互。

我希望这有帮助。

于 2010-08-26T18:13:52.130 回答
2

真正的使用NSScroller依赖于对 MVC 范式的扎实理解。Apple 的文档真正专注于显示照片和一组文本,但仅此而已。的使用NSScrollView是我过去一直在努力解决的问题。

首先,不要覆盖frame. 用于setFrame告诉scrollView工作区域有多大,然后只需简单地绘制框架所包含的区域即可。据我了解,习惯NSView和包容NSScrollView会照顾其余部分,例如何时在何处绘制什么。换句话说,忽略rect传入的边界drawRect,而是在您发送到的帧的边界内绘制scrollView;不要担心什么是可见的,什么是不可见的,因为这是框架的工作。

这就是 MVC 范式的用武之地:setFrame应该在更新模型时使用。因此,如果一个对象落在框架的当前边界之外,则使用setFrame设置新扩展的边界,然后在该区域内绘制。

于 2010-08-26T19:34:19.047 回答