2015-09-12 3 views
1

У меня есть подкласс NSView, где мне нужно нарисовать двухцветные шашки (квадраты чередующихся цветов). Следующее - это то, что у меня есть.NSView - рисование 2-цветных шашек

- (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++; 
     } 
    } 
} 

Если я запустил его, я получу квадраты чередующихся цветов. Если я изменю высоту кадра, я иногда получаю полосы чередующихся цветов. Как я могу улучшить код выше?

Спасибо.

ответ

0

Ваш метод определения квадратных цветных чередует цвет вниз столбец, а затем продолжает следующий столбец. Если у вас четное количество строк, каждая строка будет начинаться с того же цвета, что дает вам полосы.

Подумайте просто, вам нужны только два состояния - черный или белый - поэтому вместо целых чисел, сложения и нечетных/четных тестов для уменьшения целого числа до одного из двух значений начинайте с типа с двумя значениями, Boolean.

Чтобы решить проблему с нечетным или четным числом строк, используйте две переменные, одну для отслеживания цвета первого квадрата в столбце - это будет переворачивать каждую итерацию вашего внешнего контура и отслеживать цвет от текущего квадрата - для каждого столбца это начинается со значения первой переменной и переворачивает каждую итерацию внутреннего цикла.

В коде набросков до внешнего контура:

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

0

Имейте ввиду, что ваш вид не перерисовывается только потому, что он изменен! Таким образом, ваша шахматная доска сжимается или растягивается вместе с видом. Вы можете позвонить по телефону setNeedsDisplay.

+0

пардон , но нет никакой гарантии, что f - квадрат. Поэтому я не могу разделить ширину и высоту на разные числа. –

1

Другой способ рисовать шаблон шахматной доски состоит в том, чтобы сделать чек-панель 2x2 в программе рисования, добавить это в свой проект в качестве ресурса, передать это изображение +[NSColor colorWithPatternImage:], а затем вы можете просто заполнить область с этим цветом.

1

ОК, поэтому проблема заключается в том, что строка может содержать нечетное число квадратов, и в этом случае следующая строка снова отображает один и тот же шаблон. Вот как я это исправит; Я также изменил использование 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)); 
} 
+0

Спасибо за вашу попытку.Если я запускаю первый набор кода, я получаю совершенно серый фон. Если я запустил второй набор кода, я получу совершенно серый фон с белыми квадратами по диагонали. И я полагаю, у вас есть одна опечатка, где у вас есть ((i^j) & 1). –

+0

В первом блоке кода была опечатка, которую я только что зафиксировал. (Отсутствие скобок вокруг (i^j) & 1, необходимое из-за проблем с приоритетом оператора). Второй блок кода работает отлично; Я просто протестировал его. Я не уверен, почему это не сработало для вас, но если вы считаете, что его использование ((i^j) и 1) было опечаткой и попыталось исправить эту опечатку, то, возможно, вы ввели ошибку. В любом случае оба блока кода работают отлично. – bhaller

+0

Да. Первый набор кода теперь работает. Благодарю. –