【问题标题】:Erasing Cocoa Drawing done by NSRectFill?擦除由 NSRectFill 完成的 Cocoa 绘图?
【发布时间】:2011-07-01 21:37:03
【问题描述】:

我有一个NSBox,我在其中绘制小矩形,NSRectFill()。我的代码如下所示:

for (int i = 0; i <= 100; i++){


    int x = (rand() % 640) + 20;
    int y = (rand() % 315) + 196;

    array[i] = NSMakeRect(x, y, 4, 4);
    NSRectFill(array[i]);
}

这个 for 循环在网格中创建了 100 个随机放置的矩形。我一直在尝试做的是创建一种动画,由这段代码反复运行,创建一个随机出现的矩形的动画,使用这段代码:

for (int i = 0; i <= 10; i++) {      

   [self performSelector:@selector(executeFrame) withObject:nil afterDelay:(.05*i)];   

    }

顺便说一句,第一个 for 循环是 executeFrame 函数中唯一的东西。所以,我需要做的是擦除帧之间的所有矩形,所以它们的数量保持不变,它们看起来像在移动。我尝试通过再次绘制背景来做到这一点,在调用executeFrame 之前调用[myNsBox display];,但这看起来好像没有绘制矩形。之后调用它做了同样的事情,所以切换到setNeedsDisplay 而不是显示。我无法弄清楚这一点,任何帮助将不胜感激。

顺便说一句,另外一件事情是,当我尝试运行我的代码来执行帧时,而不是尝试擦除中间的矩形,所发生的只是又绘制了 100 个矩形。即使我要求抽出 1000 个,或 10,000 个。然后,如果我离开窗口并回到它(立即,时间不是这里的因素),页面更新并且矩形在那里。我试图通过[box setNeedsDisplayInRect:array[i]]; 以一种奇怪的方式来克服这个问题,导致它更新每一帧,但会删除矩形的一部分。对此的任何帮助也将不胜感激。

【问题讨论】:

  • 向您的视图发送display 消息是正确的解决方案非常罕见。你通常只需要设置它的needsDisplay 并让 AppKit 告诉它在正确的时间绘制 - 并在 AppKit 告诉它时完成所有视图的绘制,而不是在任何其他时间。

标签: objective-c cocoa drawing


【解决方案1】:

听起来你在 drawRect: 之外绘图。如果是这种情况,请将您的绘图代码移动到视图(框或某些子视图)的 drawRect: 方法中。否则,您的绘图将像您所看到的那样被 Cocoa 绘图系统踩踏。您还需要使用计时器或动画而不是循环来进行重复绘制。

【讨论】:

  • 另外值得注意的是,即使第二个for循环在drawRect:中,performSelector:withObject:afterDelay:消息意味着executeFrame消息在之后发送和接收(即,外部)drawRect:.
【解决方案2】:

我最近为尝试用圆圈做类似事情的人编写了一个示例程序。我采用的方法是创建一个圆形规格数组并在 drawRect 中绘制它们。它工作得很好。也许会有所帮助。想要整个项目的可以下载from here

@implementation CircleView

@synthesize maxCircles, circleSize;

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        maxCircles = 1000;
        circles = [[NSMutableArray alloc] initWithCapacity:maxCircles];
    }
    return self;
}

- (void)dealloc {
    [circles release];
    [super dealloc];
}

- (void)drawRect:(NSRect)dirtyRect {
    NSArray *myCircles;
    @synchronized(circles) {
        myCircles = [circles copy];
    }
    NSRect bounds = [self bounds];
    NSRect circleBounds;
    for (NSDictionary *circleSpecs in myCircles) {
        NSColor *color = [circleSpecs objectForKey:colorKey];
        float size = [[circleSpecs objectForKey:sizeKey] floatValue];
        NSPoint origin = NSPointFromString([circleSpecs objectForKey:originKey]);
        circleBounds.size.width = size * bounds.size.width;
        circleBounds.size.height = size * bounds.size.height;
        circleBounds.origin.x = origin.x * bounds.size.width - (circleBounds.size.width / 2);
        circleBounds.origin.y = origin.y * bounds.size.height - (circleBounds.size.height / 2);
        NSBezierPath *drawingPath = [NSBezierPath bezierPath];
        [color set];
        [drawingPath appendBezierPathWithOvalInRect:circleBounds];
        [drawingPath fill];
    }
    [myCircles release];
}

#pragma mark Public Methods

-(void)makeMoreCircles:(BOOL)flag {
    if (flag) {
        circleTimer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(makeACircle:) userInfo:nil repeats:YES];
    }
    else {
        [circleTimer invalidate];
    }
}

-(void)makeACircle:(NSTimer*)theTimer {
    // Calculate a random color
    NSColor *color;        
    color = [NSColor colorWithCalibratedRed:(arc4random() % 255) / 255.0
                                      green:(arc4random() % 255) / 255.0
                                       blue:(arc4random() % 255) / 255.0
                                      alpha:(arc4random() % 255) / 255.0];
    //Calculate a random origin from 0 to 1
    NSPoint origin;
    origin.x = (double)arc4random() / (double)0xFFFFFFFF;
    origin.y = (double)arc4random() / (double)0xFFFFFFFF;
    NSDictionary *circleSpecs = [NSDictionary dictionaryWithObjectsAndKeys:color, colorKey, 
                                 [NSNumber numberWithFloat:circleSize], sizeKey, 
                                 NSStringFromPoint(origin), originKey,
                                 nil];
    @synchronized(circles) {
        [circles addObject:circleSpecs];
        if ([circles count] > maxCircles) {
            [circles removeObjectsInRange:NSMakeRange(0, [circles count] - maxCircles)];
        }
    }
    [self setNeedsDisplay:YES];
}

@end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 2017-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多