开发者

NSScrollView Problems

I'm having a few problems with the NSScrollView I'm trying to use and could use some help. I've read the NSView, NSScrollView and a few other guides and references, along with questions here and cocoadev, but still can't figure these out.

(Code for my view subclass can be found below.)

My overall goal with this is an interface like that for KGChart, a needlepoint chart maker that is开发者_如何转开发 PC exclusive. (KGChart website)

  1. How can I keep things I draw in the scroll view? My -drawStitch method is executed during mouse events, where it draws a rect with a symbol on it (currently only black with a "+") to the document view of the scrollview. When I scroll it out of sight and back, it is gone and I need to retain it somehow. My idea is to try a 2D array to keep track of the stitches, but I think performance would suffer with large canvases (I would like to do 2,000x2,000, but I would settle for 500x500).

  2. If you look at the picture of my program running, you can see the difference in the grid color. The code for drawing the grid is in -drawRect and the color is set as grayColor. When the program starts, the visible grid is the lighter color, but it's darker on the parts of the canvas revealed when I scroll. I think it has to do with -drawRect being called, causing it to redraw the grid, but I don't know why it darkens the strokes as their opacity should be 1.0 already. Also, if I scroll the original frame away completely and go back, the grid is darker there as well.

  3. Is there a way for me to draw the grid at the beginning of the program that's not in drawRect so it doesn't get redrawn? I tried in -awakeFromNib and -initWithFrame, even with -lockFocus, but it didn't work. I realize the first probably didn't work because there wasn't a frame to draw to.

  4. Eventually I'll need to figure out things like the fill tool and things, so would it be better to use something like Core Graphics for this, or is the regular API OK? I would rather use the later as I know more of it than CG, but I read a bit on it too.

Final notes: I am using garbage collection and I've flipped the view and the window it's in, if those things matter at all.

Picture of the program running:

NSScrollView Problems

    - (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    [self setFrameSize:NSMakeSize(3000, 3000)];
    return self;
}

- (void)drawRect:(NSRect)rect {

    width = [self frame].size.width;
    height = [self frame].size.height;

    [[NSColor grayColor] setStroke];

    NSBezierPath* drawingPath = [NSBezierPath bezierPath];
    [NSBezierPath setDefaultLineWidth:2.0];
    [self addDashStyleToPath:drawingPath];

    int i;

    for( i = 0 ; i <= width ; i=i+30) {
        [drawingPath moveToPoint:NSMakePoint(i, 0)]; 
        [drawingPath lineToPoint:NSMakePoint(i, height)]; 
    } 

    for( i = 0 ; i <= height ; i=i+30) { 
        [drawingPath moveToPoint:NSMakePoint(0,i)]; 
        [drawingPath lineToPoint:NSMakePoint(width, i)]; 
    }

    [drawingPath stroke];

}
-(void)drawStitch{

    NSPoint thisPoint;
    NSPoint fillPoint;
    NSRect fillRect;


    float thisPointX = [self calculatedItemBounds].origin.x + 5.0;
    float thisPointY = [self calculatedItemBounds].origin.y - 8.0;

    float fillPointX = [self calculatedItemBounds].origin.x + 1.0;
    float fillPointY = [self calculatedItemBounds].origin.y + 1.0;

    thisPoint.x = thisPointX;
    thisPoint.y = thisPointY;

    fillPoint.x = fillPointX;
    fillPoint.y = fillPointY;

    fillRect.origin.x = fillPoint.x;
    fillRect.origin.y = fillPoint.y;

    fillRect.size.width = 28;
    fillRect.size.height = 28;

    NSMutableDictionary *theAttributes;

    theAttributes = [[NSMutableDictionary alloc] init];
    [theAttributes setObject: [NSColor whiteColor] forKey:NSForegroundColorAttributeName];
    [theAttributes setObject: [NSFont fontWithName:@"Helvetica" size: 32] forKey: NSFontAttributeName];

    NSString *theString = @"+";
    [self lockFocus];
    [[NSColor blackColor] setFill];
    [NSBezierPath setDefaultLineWidth:2.0];
    [self addDashStyleToPath:[NSBezierPath bezierPathWithRect:[self calculatedItemBounds]]];
    [NSBezierPath fillRect:fillRect];

    NSNumber* myInteger = [NSNumber numberWithInt:310];

    [myArray setObject:myInteger :location.x/30 :location.y/30];
    NSLog(@"%@", [myArray objectInSection:location.x/30 :location.y/30]);
    NSLog(@"%f, %f", location.x/30,location.y/30);

    [theString drawAtPoint:thisPoint withAttributes:theAttributes];
    [self displayIfNeededInRectIgnoringOpacity:[self calculatedItemBounds]];

    [self unlockFocus];
    [theAttributes release];
}

I'm pretty noobish at this, obviously, so thank you for all your help!


By default, the content view (an instance of NSClipView) of an NSScrollView does some performance optimisation by copying its existing rendered image when scrolling. Much of the time this works fine but when you are drawing a complex custom view it is often unwanted behaviour, so you should turn it off.

If you're using a nib to define your UI, just select the scroll view in IB and un-check the "Copies on Scroll" checkbox.

You can set this programmatically using the ‑setCopiesOnScroll: method of NSClipView:

[[scrollView contentView] setCopiesOnScroll:NO];


I do believe I got this fixed. For it to work, I had to rearrange my code to do the drawing in drawRect, rather than using lockFocus in my drawStitch method (I need to read up on MVC designing). Also, the scrollview only seems to redraw the latest bezier path, so to make multiple "stitches" I need to keep appending the path with rects.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜