【问题标题】:Cocoa: NSView drawRect painting over IBOutletsCocoa:在 IBOutlets 上绘制 NSView drawRect
【发布时间】:2011-11-17 13:37:14
【问题描述】:

我在 IB 中有一个 NSView,它位于应用程序窗口的上方。我有一个分配给 NSView 的 NSView (AddSource) 子类。

在 awakeFromNib 我实例化视图:

//add a new Add Source class
addSourceView = [[AddSource alloc] initWithFrame:NSMakeRect(0.0, 959.0, 307.0, 118.0)];
[[winMain contentView] addSubview:addSourceView];

在 addSourceView 的 drawRect 方法中,我在视图中添加了一个白色背景:

[[NSColor whiteColor] set];
NSRectFill(rect);
[self setNeedsDisplay:YES];//added this to see if it might solve the problem

在 winMain 的 contentView 中,我有一个 NSButton,单击它会将 addSourceView 滑到窗口上:

NSRect addSourceViewFrame = [addSourceView frame];
addSourceViewFrame.origin.y = 841.0;
[[addSourceView animator] setFrame:addSourceViewFrame];

但似乎该应用正在绘制我放置在 IB 中的 NSView 上的 IBOutlets。如果在 IB 中,我重新定位 NSView 以便在应用程序启动时它在屏幕上一切正常,则 IBOutlets 和背景颜色都在那里。

我不确定为什么会这样。我以前做过这个,没有任何问题。这次我一定要做点不一样的事。

感谢您的帮助。

*note - 在第 3 次屏幕截图中,当我说这是应用程序打开时的样子时,那是我对 NSView 的 Y 位置进行硬编码的时候。当它正常运行时,它应该以屏幕截图 1 的形式打开。

【问题讨论】:

  • 你似乎很困惑..在drawRect中随机尝试-setNeedsDisplay之类的东西不是答案。你读过希勒加斯的书吗?
  • 困惑,是的,但不是你想的那样。我把 setNeedsDisplay 放在那里看看会发生什么。
  • 好吧,我承认 - 我很困惑。如果您在 IB 或 -awakeFromNib 中创建 AddSourceView ,您的描述尚不清楚
  • 我有一个名为 AddSource 的类(NSView 的子类)。在 IB 中,我创建了一个 NSView,将其作为类添加 AddSource 并将其放置在窗口之外。在 awakeFromNib 上,我实例化了这个类,并在它的 drawRect 中用白色填充它。这发生在用户没有看到视图的情况下。当用户单击添加源按钮(+ 号)时,视图会向下滑动,用户可以填写所需的信息(屏幕截图 3)。但我得到的是屏幕帽 2。
  • 这就是我添加 setNeedsDisplay 的原因,我想可能是因为我正在为视图“绘制”一种颜色,我必须重新绘制我在 IB 中放置的对象(文本字段和按钮)。编辑:我可以以编程方式添加文本字段和按钮(在 AddSource 类的 drawRect 中,它工作正常,但我宁愿不必这样做。

标签: cocoa nsview drawrect


【解决方案1】:

您的按钮和自定义视图很可能是同级的,即它们都是窗口内容视图的子视图。由于兄弟姐妹是“堆叠”的,具体取决于它们的添加顺序,所以当您在代码中添加视图时,它会被添加到按钮之上。您应该能够通过显式指定视图相对于其新兄弟的位置来修复它,如下所示:

[[winMain contentView] addSubview:addSourceView positioned:NSWindowBelow relativeTo:nil];

应该将它放在窗口内容视图的任何现有子视图下方。此外,删除 drawRect 中的 setNeedsDisplay: 行,这会导致不必要的、可能是无限的重绘。

编辑:好的,我明白你在做什么。

我建议通过将“自定义视图”对象拖到左侧(垂直对齐的存档对象部分)并在那里添加控件来在 NIB 中创建一个独立视图,这应该确保控件实际上是视图,然后您可以在代码中创建对存档视图的引用,并根据需要动态添加/删除它。

不过,老实说,您可能应该为这些类型的模式对话框使用工作表。为什么要重新发明轮子,让你的应用在这个过程中变得更丑?

【讨论】:

  • 感谢调频。但这只会将我正在向下滑动的 NSView 定位在屏幕上的其他对象(放置在 IB 中)的后面。请参阅 OP,我添加了一些屏幕截图以使事情更清晰。
【解决方案2】:

您在窗口中添加了 两个 AddSource 视图。您在 IB 中添加了一个 - 此视图包含连接到 IBOutlets 的文本字段和按钮,并且位于窗口外。

然后在-awakeFromNib 中创建另一个空白AddSource 视图(不包含任何内容)并将其动画到窗口中。

我不能高度推荐 Hillegass 作为 IB 的最佳介绍和构建 Cocoa 应用程序的正确方法。

此外,断言有助于确保您认为正在发生的事情实际上就是正在发生的事情。

如果您确定您在 IB 中的视图中添加了一个按钮,请断言它是这样的:-

- (void)awakeFromNib {
      NSAssert( myButton, @"did i hook up the outlet?");
}

NSAssert 是一个在发布版本中开销为零的宏。

-drawRect 调用[self setNeedsDisplay:YES] 只会导致再次调用相同的-drawRect。这会给你带来很大的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-24
    • 2011-04-26
    • 2013-02-16
    • 2023-04-06
    • 2017-01-28
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    相关资源
    最近更新 更多