【问题标题】:How should I wrap a custom NSView in an NSScrollView?我应该如何在 NSScrollView 中包装自定义 NSView?
【发布时间】:2011-04-04 09:34:28
【问题描述】:

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。我使用翻转,所以它在左上角,滚动后它最终位于可见区域之外。
  • 根本不绘制此无关矩形之外的可见区域。

除此之外我什么都不知道。 似乎绘制的矩形被裁剪到滚动视图在窗口中的位置、大小或其他方面——但它没有考虑滚动的“位置”。

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

问候和希望,

不是瑞克·阿斯特利

【问题讨论】:

标签: objective-c cocoa clipping nsscrollview


【解决方案1】:

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

【讨论】:

  • 我会马上尝试这个,因为似乎有一种不覆盖 -frame 的普遍冲动。不知道这很重要——我真的只想设置一次框架,并认为这是一种快速的方法。
  • 甜,它奏效了。太感谢了。我会记住这个区别,希望不会再纠缠你关于新手的事情。
【解决方案2】:

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

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

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

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

我希望这会有所帮助。

【讨论】:

  • 谢谢,这证实了对优化的一些怀疑。目前这都是原型工作,因为我想为几个可能需要滚动的项目确定这些东西。
【解决方案3】:

NSScroller 的使用确实依赖于对 MVC 范式的扎实理解。 Apple 的文档真正专注于显示照片和一组文本,但仅此而已。 The use of NSScrollView is something that I've struggled with in the past.

首先,不要覆盖frame。使用setFrame 告诉scrollView 工作区域有多大,然后只需简单地在框架包含的区域中绘制。据我了解,自定义NSView 和包含NSScrollView 负责其余部分,例如何时在何处绘制什么。换句话说,忽略传递给drawRectrect 的边界,而是在您发送给scrollView 的帧的边界内绘制;不要担心什么是可见的,什么是不可见的,因为这是框架的工作。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    • 2021-03-03
    • 2017-06-27
    相关资源
    最近更新 更多