Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

bahlquist

macrumors member
Original poster
Oct 6, 2010
41
0
I am having trouble drawing to a view more than once. I want the following program to fill my view with white and then draw a black path from a given point (coordinates (100,100)) to the coordinates of a mouseDown event.

I have set up a custom view in IB that uses my class BADraw which is as follows:

BADraw.h:

Code:
#import <Cocoa/Cocoa.h>
@interface BADraw : NSView {}
@end



BADraw.m:

Code:
#import "BADraw.h"

@implementation BADraw
-(void)mouseDown:(NSEvent*)event{
	NSPoint p;
	p.x = 100;
	p.y = 100;
	NSBezierPath* path = [[NSBezierPath alloc] init];
	[path moveToPoint:p];
	[path setLineWidth:1.0];
	[[NSColor blackColor] set];
	[path lineToPoint:[event locationInWindow]];
	[path stroke];
        
        //I tried using the following methods to get the path to display:
	[self lockFocus];
	[self setNeedsDisplay:YES];
	[self display];
	[self unlockFocus];

	[path release];
}

-(void)drawRect:(NSRect)rect{
	[[NSColor whiteColor] set];
	[NSBezierPath fillRect:[self bounds]];
}

@end

IB information:
I dragged a custom view from the IB palette into my window and set it to use BADraw.

Output:
The output is a white rectangle filling the window. No paths appear when I click.

I'm obviously missing something basic here, but I don't know what. What do I need to do?
 
Several things.

1. To get the mouse location relative to your view's bounds, use:
Code:
[self convertPoint:[event locationInWindow] fromView:nil]

2. All drawing for your view should go in the drawRect: method.

3. lockFocus/unlockFocus/display are really only used on an NSView when you're drawing into it from a background thread, and you probably will never be doing that :)

4. To get the view to redraw, just use setNeedsDisplay:YES

So, here's how it should look:
Code:
#import <Cocoa/Cocoa.h>
@interface BADraw : NSView
{
    NSPoint mouseLoc;
}
@end

#import "BADraw.h"

@implementation BADraw

- (void)awakeFromNib
{
    mouseLoc = NSMakePoint(-1, -1);
}

- (void)mouseDown:(NSEvent*)event
{
    mouseLoc = [self convertPoint:[event locationInWindow] fromView:nil];
    [self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)rect
{
    [[NSColor whiteColor] set];
    [NSBezierPath fillRect:[self bounds]];

    if (NSEqualPoints(mouseLoc, NSMakePoint(-1, -1)))
        return;

    NSPoint p;
    p.x = 100;
    p.y = 100;
    NSBezierPath *path = [NSBezierPath bezierPath];
    [path moveToPoint:p];
    [path setLineWidth:1.0];
    [path lineToPoint:mouseLoc];
    [[NSColor blackColor] set];
    [path stroke];
}

@end
 
Thanks! If I wanted the previously drawn paths to remain in the view, how could I do that? I could just append to a global path variable each time I click and then redisplay this path using setNeedsDisplay:, but in the application I am actually making each click creates a path that contains upwards of 50,000 points and this will slow things down after a dozen clicks. Is there a way to draw the new path without redisplaying everything? (This question is relevant to the above code.)
 
Thanks! If I wanted the previously drawn paths to remain in the view, how could I do that? I could just append to a global path variable each time I click and then redisplay this path using setNeedsDisplay:, but in the application I am actually making each click creates a path that contains upwards of 50,000 points and this will slow things down after a dozen clicks. Is there a way to draw the new path without redisplaying everything? (This question is relevant to the above code.)

-setNeedsDisplayInRect: might reduce the amount of drawing needed, if you have such a method, and it works to minimize drawing appropriately.

Your other option might be to draw the existing lines into a temporary NSImage object, with a bitmap image rep, which you could use as a sort of offscreen cache (I would start the cache image after you have a few hundred lines and add lines to it incrementally so that you still have a few dozen uncached lines to draw over it).
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.