setNeedsDisplay不会导致dirtyRect填充整个视图

时间:2016-08-01 10:42:48

标签: cocoa nsview setneedsdisplay

我遇到了一个令人困惑的问题。我尝试绘制图表,并在每次将新数据添加到图表时调用setNeedsDisplay

图表会通过addData:(NSNotification*)theNote接收新数据,然后会尝试多种方式调用setNeedsDisplay来重绘视图。但是,此时数据无法正确重绘。如果我将窗口拖到另一个屏幕,或者如果我点击图表并从setNeedsDisplay调用mouseDown,则视图会重新正确重绘。通过使用dirtyRect监控NSLog的大小,我将问题跟踪到的dirtyRect太小了。但我甚至无法猜测如何纠正这一点。那里有什么想法吗?

//
//  graphView.m
//  miniMRTOF
//
//  Created by シューリ ピーター on 8/1/16.
//  Copyright © 2016 シューリ ピーター. All rights reserved.
//

#import "graphView.h"

@implementation graphView

- (id)initWithFrame:(NSRect)frame{
    self = [super initWithFrame:frame];
    if (self) {

        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
        [nc addObserver:self selector:@selector(addData:) name:AddDataNotification object:nil];

        theData = [[NSMutableArray alloc] init];

        NSLog(@"graphView initialized");

    }
    return self;
}

-(void)addData:(NSNotification*)theNote{
    NSLog(@"graphView has gotten the note");

    NSMutableArray *theThermalArray = [[NSMutableArray alloc] init];

    theThermalArray = [[theNote userInfo] objectForKey:@"theThermals"];
    float ave = 0;
    int n = 0;
    for (int i=0; i<16; i++){
        float f_i = [[theThermalArray objectAtIndex:i] floatValue];
        ave += f_i;
        if(f_i != 0) n++;
    }
    ave /= n;

    [theData addObject:[NSNumber numberWithFloat:ave]];
    NSLog(@"graphView has added %0.3f and now has %lu components", ave, (unsigned long)[theData count]);
    [self setNeedsDisplay:YES];
    [[self.window contentView] setNeedsDisplay:YES];
    [self performSelectorOnMainThread:@selector(redraw) withObject:nil waitUntilDone:YES];
}

-(void)redraw{
    [self setNeedsDisplay:YES];
    [[self.window contentView] setNeedsDisplay:YES];

}

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    // Drawing code here.

    NSLog(@"dirtyRect: x:%0.2f, y:%0.2f, w:%0.2f, h:%0.2f", dirtyRect.origin.x, dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height);

    float xScale = ([self bounds].size.width)/((float)[theData count]+1e-3);//(maxX - minX);
    float yScale = [self bounds].size.height/(maxT - minT);

    [[NSColor whiteColor] set];
    NSRect fillArea = [self bounds];
    [NSBezierPath fillRect:fillArea];

    if(dirtyRect.size.height < 100){
        NSLog(@"small dirtyRect");
        [[NSColor grayColor] set];
        [NSBezierPath fillRect:dirtyRect];
    }
    dirtyRect = [self bounds];

    int dataCount = (int)[theData count];

    NSBezierPath *pathForFrame = [[NSBezierPath alloc] init];

    NSPoint P0 = {1,1};
    NSPoint P1 = {1, [self bounds].size.height};
    NSPoint P2 = {[self bounds].size.width, 1};

    [pathForFrame moveToPoint:P0];
    [pathForFrame lineToPoint:P1];
    [pathForFrame moveToPoint:P0];
    [pathForFrame lineToPoint:P2];

    [[NSColor redColor] set];
    [pathForFrame stroke];

    NSLog(@"drawing %i points", dataCount);

    NSBezierPath *pathForPlot = [[NSBezierPath alloc] init];
    if(dataCount<maxRawPlotData){
        if(dataCount>1){

            NSPoint p1;
            p1.y = [[theData objectAtIndex:0] floatValue];
            p1.x = (0-minX)*xScale;
            p1.y = (p1.y-minT)*yScale;
            [pathForPlot moveToPoint:p1];
            NSLog(@"point: %0.1f, %0.1f", p1.x, p1.y);
        }
        for(int i=1; i<dataCount; i++){

            NSPoint p;
            p.y = [[theData objectAtIndex:i] floatValue];
            p.x = (i-minX)*xScale;
            p.y = (p.y-minT)*yScale;
            [pathForPlot lineToPoint:p];
            NSLog(@"point: %0.1f, %0.1f", p.x, p.y);
        }
    }

    [[NSColor blackColor] set];
    [pathForPlot stroke];

    [txtMaxX setStringValue:[NSString stringWithFormat:@"%0.0f",maxX]];

}


-(void)controlTextDidEndEditing:(NSNotification *)obj{
    NSLog(@"controlTextDidEndEditing");
    if([[obj object] isEqualTo:txtMaxT]){
        maxT = [txtMaxT floatValue];
        [txtMidT setStringValue:[NSString stringWithFormat:@"%0.1f",0.5*(maxT+minT)]];
    }
    else if([[obj object] isEqualTo:txtMinT]){
        minT = [txtMinT floatValue];
        [txtMidT setStringValue:[NSString stringWithFormat:@"%0.1f",0.5*(maxT+minT)]];
    }
    else if([[obj object] isEqualTo:txtMaxX]){
        maxX = [txtMaxX floatValue];
    }
    else if([[obj object] isEqualTo:txtMinX]){
        minX = [txtMinX floatValue];
    }
    else NSLog(@"How'd we get here?");

    [[[obj object] window] makeFirstResponder:[[obj object] window].contentView];
    [self setNeedsDisplay:YES];
    [self display];
}

-(void)mouseDown:(NSEvent *)theEvent{
    NSLog(@"mousedown");
    [self setNeedsDisplay:YES];
}

@end

0 个答案:

没有答案