Joson Daniel
Joson Daniel

Reputation: 409

How to change background color for NSview in Cocoa

I want to change background color for many nsview. I override drawRect: on subclass NSview but i don't know how to set background color for myview( is reference IBOUTLET). please help me. Thanks so much

Code for CustomView.h

 #import <Cocoa/Cocoa.h>

@interface CustomView : NSView

@end

Code for CustomView.m

 #import "CustomView.h"

@implementation CustomView

- (void) drawRect:(NSRect)dirtyRect {
    [[NSColor whiteColor] setFill];
    NSRectFill(dirtyRect);
    [super drawRect:dirtyRect];
}

@end

And in main class, i added #import "CustomView.h" but i don't know how to set background for myview.

Upvotes: 1

Views: 6784

Answers (2)

gypsyDev
gypsyDev

Reputation: 1299

I'm super late, but this is how I do it - there's no need to sub class:

NSView *myview = [NSView new];
[view setWantsLayer:YES];
view.layer.backgroundColor = [NSColor greenColor].CGColor;

Upvotes: 0

uchuugaka
uchuugaka

Reputation: 12782

Welcome to Cocoa drawing. Cocoa drawing uses Quartz which is a PDF model. Drawing in this occurs in a back to front procedural order.

In Quartz drawing there is a drawing environment state object called the Graphics Context. This is an implicit object in many of the drawing ops in AppKit. (in Core Graphics or other APIs it could need to be explicitly called)

You tell the Graphics Context what the current color and other parameters are, then draw something, then change parameters and draw more, etc... In AppKit, you do this by sending a message to the NSColor object, which is weird. but that's how it works.

In your drawRect: method you should call super first usually, because you probably want your drawing on top of that...

- (void) drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

   // This next line sets the the current fill color parameter of the Graphics Context
    [[NSColor whiteColor] setFill];
   // This next function fills a rect the same as dirtyRect with the current fill color of the Graphics Context.
    NSRectFill(dirtyRect);
   // You might want to use _bounds or self.bounds if you want to be sure to fill the entire bounds rect of the view. 
}

If you want to change the color, you'll need an @property NSColor You might need more than one for your drawing.

That allows you to set the color.

You might want the view to use KVO and observe its own color property then draw itself if the color property changes.

You could do a lot of different things to set the color. (a button or pallette elsewhere) But all of them would eventually result in sending a message to set the color of a property of your view for drawing.

Finally, if you want to update the drawing, you need to call [myView setNeedsDisplay:YES]; where myView is a reference to an instance of the NSView subclass. There is also display but that's forceful. setNeedsDisplay: says to schedule it on the next run of the event loop (runLoop). display kind of makes everything jump to that right away. The event loop comes back around fast enough you shouldn't force it. Of note, setNeedsDisplay: is the entire view. In a fancy ideal world with complex views, you might want to more appropriately optimize things by calling setNeedsDisplayInRect: where you designate a specific CG/NSRect of the view as needing to be redrawn. This allows the system to focus redrawing to the smallest union rect possible in the window.

Upvotes: 10

Related Questions