NSView-绘制双色方格



我有一个NSView的子类,需要在其中绘制双色方格(交替颜色的正方形(。以下是我所拥有的。

- (void)drawRect:(NSRect)rect {    
    NSInteger k = 1;
    for (int j = 0;  j < self.frame.size.width; j += 20) {
        for (int i = 0; i < self.frame.size.height; i +=20) {
            if (k%2 == 0) {
                [[NSColor whiteColor] set];
            }
            else {
                [[NSColor lightGrayColor] set];
            }
            [NSBezierPath fillRect:NSMakeRect(j,i,20,20)];
            k++;
        }
    }
}

如果我运行它,我会得到交替颜色的正方形。如果我改变边框高度,有时会得到交替颜色的条纹。如何改进上面的代码?

谢谢。

绘制棋盘图案的另一种方法是在绘图程序中制作一个2x2棋盘,将其作为资源添加到项目中,将该图像传递给+[NSColor colorWithPatternImage:],然后您就可以用该颜色填充一个区域。

好的,所以问题是一行中可能有奇数个正方形,在这种情况下,下一行再次显示相同的模式。以下是我将如何修复它;我还将您对NSBezierPath的使用更改为NSRectFill((,因为后者在概念上更简单,而且可能更快。

- (void)drawRect:(NSRect)rect {    
    for (int j = 0;  j * 20 < self.frame.size.width; j++) {
        for (int i = 0; i * 20 < self.frame.size.height; i++) {
            if (((i^j) & 1) == 0)
                [[NSColor whiteColor] set];
            else
                [[NSColor lightGrayColor] set];
            NSRectFill(NSMakeRect(j*20,i*20,20,20));
        }
    }
}

(i^j) & 1使用逐位异或(^运算符(,然后使用逐位和(&运算符(来组合行和列索引的奇偶状态。有各种方法可以优化乘法,但这段代码似乎是最清晰的方法。一个稍微干净一点的版本可以运行得更快,也许可以避免一些绘制伪像,它将首先清除为一种颜色,然后只绘制相反颜色的正方形:

- (void)drawRect:(NSRect)rect {
    [[NSColor whiteColor] set];
    NSRectFill(rect);
    [[NSColor lightGrayColor] set];
    for (int j = 0;  j * 20 < self.frame.size.width; j++)
        for (int i = 0; i * 20 < self.frame.size.height; i++)
            if ((i^j) & 1)
                NSRectFill(NSMakeRect(j*20,i*20,20,20));
}

您确定正方形颜色的方法将颜色向下交替一列,然后继续下一列。如果你有偶数行,每一行都会以相同的颜色开始,给你条纹。

简单地说,你只需要两个状态——黑色或白色——所以不用整数、加法和奇数/偶数测试来将整数减少到两个值中的一个,只需从一个只有两个值的类型开始,即布尔类型。

为了处理奇数或偶数行的问题,使用两个变量,一个跟踪列中第一个正方形的颜色-这将翻转外循环的每次迭代,另一个跟踪当前正方形的颜色。对于每列,这从第一个变量的值开始,并翻转内循环的每次循环。

在代码大纲中,在外循环之前:

BOOL colStartsWhite = YES; // or NO, you decide - this is the corner color

外环内部:

BOOL squareIsWhite = colStartsWhite; // inner tracker
colStartsWhite = !colStartsWhite; // flip ready for next column

内环内部:

if (squareIsWhite) ... else ... // fill the square
squareIsWhite = !squareIsWhite; // flip for next square

HTH

请记住,视图不会因为调整了大小而重新绘制!因此,你的棋盘会随着视图一起被挤压或拉伸。呼叫setNeedsDisplay由您决定。

最新更新