3

我有一个自定义的 NSView,它曾经在 NIB 中创建并分配为 NSMenuItem 的视图,效果很好,但现在我想用代码创建视图(我可以向你保证这是有充分理由的),看起来并不难但是视图实际上并没有绘制。

即使我发送“setNeedsDisplay:”消息,也不再调用以前调用以在需要时绘制视图的“drawRect:”消息。

我用图像初始化视图并设置(视图的大小以匹配图像大小)这似乎有效,因为菜单项的大小正确,但没有图像。

这里会发生什么?

这是初始化视图的代码:

-(id)initWithImage:(NSImage*)image
{
    self = [super init];

    if (self != nil)
    {
        self.imageToDisplay = image;

        // this bit does get called and resizes the view to match the image size
        NSRect imageBounds = NSMakeRect(0.0f, 0.0f, imageToDisplay.size.width, imageToDisplay.size.height);     
        [self setBounds:imageBounds];
        [self setFrame:imageBounds];

        [self setHidden:NO];
        [self setAlphaValue:1.0f];

        [self setAutoresizesSubviews:YES];
    }

    return self;
}

这是绘制没有被调用的视图的代码

// this is never called
-(void)drawRect:(NSRect)dirtyRect
{
    if (imageToDisplay == nil)
        return;

    NSRect imageBounds = NSMakeRect(0.0f, 0.0f, imageToDisplay.size.width, imageToDisplay.size.height);

    [self setBounds:imageBounds];
    [self setFrame:imageBounds];

    [imageToDisplay drawInRect:[self bounds]
                      fromRect:imageBounds
                     operation:NSCompositeSourceAtop
                      fraction:1.0f];
}

这是添加视图的菜单项的代码。

-(void)awakeFromNib
{
    MyCustomView* view = [[MyCustomView alloc] init];

    [self setView:view];

    // i would have expected the image to get drawn at this point
    [view setNeedsDisplay:YES];
}
4

1 回答 1

1

You have to set your view's frame before you can set its bounds. In your -init..., either swap the two set... calls, or remove the setBounds: (bounds is set to {(0,0), (frame.size.width, frame.size.height)} by default anyways) and everything should work. I also don't think that you need to set frame and bounds again in drawRect, and in fact it seems like a bad idea to change those when focus is already locked on your view; at best it will cause weird flashing if the values are actually different.

UPDATE: just saw this note in the View Programming Guide:

Note: Once an application explicitly sets the bounds rectangle of a view using any of the setBounds... methods, altering the view's frame rectangle no longer automatically changes the bounds rectangle. See "Repositioning and Resizing Views" for details.

于 2011-03-12T21:19:19.587 回答