【问题标题】:How to add an NSView to NSWindow in a Cocoa app?如何在 Cocoa 应用程序中将 NSView 添加到 NSWindow?
【发布时间】:2012-09-11 05:58:09
【问题描述】:

由于Xcode中OS X应用的模板看起来类似于一个空的应用模板,下面是用来添加一个视图和一个按钮(暂时不使用Interface builder):

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{       
    NSView *view = [[NSView alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)];

    view.layer.backgroundColor = [[NSColor yellowColor] CGColor];

    [self.window.contentView addSubview:view];

    NSRect frame = NSMakeRect(10, 40, 90, 40);
    NSButton* pushButton = [[NSButton alloc] initWithFrame: frame]; 
    pushButton.bezelStyle = NSRoundedBezelStyle;

    [self.window.contentView addSubview:pushButton];

    NSLog(@"subviews are %@", [self.window.contentView subviews]);   
}

iOS 上的类似代码应该会产生一个黄色框和一个按钮,但上面的代码只产生一个按钮,但视图不会显示。上面的代码是不是有问题,如何让它以黄色背景显示视图?

【问题讨论】:

    标签: objective-c macos cocoa nsview nswindow


    【解决方案1】:

    使用 NSView 类的setWantsLayer: 方法。

    NSView *view = [[NSView alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)];
    [view setWantsLayer:YES];
    view.layer.backgroundColor = [[NSColor yellowColor] CGColor];
    
    [self.window.contentView addSubview:view];
    
    NSRect frame = NSMakeRect(10, 40, 90, 40);
    NSButton* pushButton = [[NSButton alloc] initWithFrame: frame]; 
    pushButton.bezelStyle = NSRoundedBezelStyle;
    
    [self.window.contentView addSubview:pushButton];
    
    NSLog(@"subviews are %@", [self.window.contentView subviews]);  
    

    【讨论】:

    • NSView 似乎没有 backgroundColor 属性。我有点想念UIKit...!
    • 这个答案很糟糕。 explicitly told 不能在 layer-backed 视图中触摸支持层(您使用 -setWantsLayer: 而没有先调用 -setLayer: 的视图)。来自文档:当使用 layer-backed 视图时,您永远不应该直接与 layer 交互
    • 你的意思是,应该先实例化一个CALayer,设置为view.layer,然后设置wantsLayer为YES,设置背景颜色?
    • @JeremyL:不,因为层托管视图(如果您设置层,您会得到)不能有任何子视图。如果您希望您的按钮位于背景之上,则它需要是一个子视图(非分层的重叠视图可能无法正常工作,如果一个是图层托管,几乎肯定不会)。由于您的按钮需要是子视图,因此黄色背景不能是图层托管视图。
    • 如何将自定义类链接到该 view ? @NSAddict
    【解决方案2】:

    为了扩展 Kevin Ballard 的建议,执行此操作的经典方法是继承 NSView 并覆盖 -drawRect: 方法。 NSRectFill 是一个非常方便的函数,无需创建贝塞尔路径即可填充矩形:

    - (void)drawRect:(NSRect)rect
    {
        [[NSColor yellowColor] set];
        NSRectFill(rect);
    }
    

    【讨论】:

      【解决方案3】:

      默认情况下,Cocoa 中的NSViews 不支持层。我怀疑如果你输入

      NSLog(@"%@", view.layer);
      

      你会看到它是nil

      在 iOS 中,所有视图都有层。但是在 OS X 上,视图没有层。此外,在 OS X 上还有 2 种 layer-backed view 的“模式”。有所谓的“layer-backed views”和“layer-hosting view”。 layer-backed view 使用 CoreAnimation layer 来缓存绘制的数据,但是你不能以任何方式与 layer 交互。层托管视图使用您明确提供的CALayer,您可能会随心所欲地弄乱该层。但是,对于图层托管视图,您可能不会添加任何子视图,或使用内置的 NSView 绘图机制。层托管视图只能用作 CoreAnimation 层层次结构的根。

      考虑到这一切,您可能应该完全避免在视图中使用 CoreAnimation。

      NSBox 可能会做你想做的事。您当然可以在那里设置填充颜色,关闭边框并将样式设置为自定义。我只是不能 100% 确定它会画成一个简单的填充颜色矩形。或者,您可以定义自己的 NSView 子类,在 -drawRect: 中绘制颜色。

      【讨论】:

      • 你知道如何让视图显示为黄色背景吗?
      • @JeremyL:我现在正在研究这个。我主要做 iOS,所以请稍等。
      • @JeremyL,我总是像凯文提到的那样,使用 NSBox 而不是自定义视图。只需将其类型设置为自定义,然后您可以(在 IB 或代码中)设置其背景颜色、边框颜色(或无边框,如果您愿意)和圆角。
      • 我尝试了一个 NSBox,但它有一个“标题”,并且没有 backgroundColor 属性
      • @JeremyL:您可以取消标题,将框类型设置为自定义,将边框类型设置为无。然后背景颜色由fillColor 控制。我鼓励你创建一个 xib,将一个 NSBox 拖到你的画布上,并在那里使用属性。
      猜你喜欢
      • 2016-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-20
      • 1970-01-01
      • 2014-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多