2012-05-22 6 views
1

Я пытаюсь создать NSMatrix из NSButtonCell s, где между нулевыми и четырьмя кнопками можно выбрать (переключается). Я пробовал следующий (тестовый) код, но не уверен, как я могу предоставить требуемые функции. Возможно, это невозможно с NSMatrix, и мне нужно посмотреть на альтернативный элемент управления или создать собственный?NSMatrix с несколькими кнопками переключения?

@interface MatrixView : NSView 
{ 
    NSScrollView *_scrollView; 
    NSMatrix *_matrixView; 
} 
@end 

@implementation MatrixView 

- (id)initWithFrame:(NSRect)frameRect 
{ 
    NSLog(@"initWithFrame. frameRect=%@", NSStringFromRect(frameRect)); 
    self = [super initWithFrame:frameRect]; 
    if (self != nil) 
    { 
     _scrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, frameRect.size.width, frameRect.size.height)]; 
     [_scrollView setBorderType:NSNoBorder]; 
     [_scrollView setHasVerticalScroller:YES]; 
     [_scrollView setHasHorizontalScroller:NO]; 
     [_scrollView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; 

     NSSize contentSize = [_scrollView contentSize]; 
     contentSize.height = 300; 

     // Make it 3 x however-many-buttons-will-fit-the-height 
     CGFloat gap = 8.0; 
     CGFloat width = (contentSize.width/3.0) - (gap * 2.0); 
     NSUInteger rows = (contentSize.height/(width + gap)); 

     NSLog(@"width=%f, rows=%lu", width, rows); 

     NSButtonCell *prototype = [[NSButtonCell alloc] init]; 
     [prototype setTitle:@"Hello"]; 
     [prototype setButtonType:NSToggleButton]; 
     [prototype setShowsStateBy:NSChangeGrayCellMask]; 
     _matrixView = [[NSMatrix alloc] initWithFrame:NSMakeRect(0, 0, contentSize.width, contentSize.height) 
               mode:NSListModeMatrix 
              prototype:prototype 
             numberOfRows:rows 
             numberOfColumns:3]; 
     [_matrixView setCellSize:NSMakeSize(width, width)]; 
     [_matrixView setIntercellSpacing:NSMakeSize(gap, gap)]; 
     [_matrixView setAllowsEmptySelection:YES]; 
     [_matrixView sizeToCells]; 
     [_scrollView setDocumentView:_matrixView]; 
     [self addSubview:_scrollView]; 
     [self setAutoresizesSubviews:YES]; 
     [prototype release]; 
    } 

    return self; 
} 

... 
+0

Вы, конечно, может иметь матрица с несколькими переключающими кнопками - я сделал один в IB, с NSButtonCells (нажмите на push off type) и матрицу в режиме подсветки. Это показало кнопки, которые остались подсвеченными, пока вы не подтолкнули их снова. Ограничение только до 4, немного сложнее - еще не совсем понял, что один из них еще нет. – rdelmar

+0

@rdelmar Я только что изменил приведенный выше код, чтобы использовать кнопки push-on-push-off и поместить матрицу в режим подсветки, но она не работает по желанию (режим push-on-push-off отменяется по матрице, и ничто не задерживается). Было ли что-то еще, что нужно было установить? – trojanfoe

ответ

1

Я получил это для работы со следующим подклассом NSMatrix. Я добавил одно свойство, onCount, чтобы отслеживать, как много кнопок были во включенном состоянии:

@implementation RDMatrix 
@synthesize onCount; 

-(id) initWithParentView:(NSView *) cv { 
    NSButtonCell *theCell = [[NSButtonCell alloc ]init]; 
    theCell.bezelStyle = NSSmallSquareBezelStyle; 
    theCell.buttonType = NSPushOnPushOffButton; 
    theCell.title = @""; 
    if (self = [super initWithFrame:NSMakeRect(200,150,1,1) mode:2 prototype:theCell numberOfRows:4 numberOfColumns:4]){ 
     [self setSelectionByRect:FALSE]; 
     [self setCellSize:NSMakeSize(40,40)]; 
     [self sizeToCells]; 
     self.target = self; 
     self.action = @selector(buttonClick:); 
     self.drawsBackground = FALSE; 
     self.autoresizingMask = 8; 
     self.allowsEmptySelection = TRUE; 
     self.mode = NSHighlightModeMatrix; 
     self.onCount = 0; 
     [cv addSubview:self]; 
     return self; 
    } 
    return nil; 
} 


-(IBAction)buttonClick:(NSMatrix *)sender { 
    NSUInteger onOrOff =[sender.selectedCells.lastObject state]; 
    if (onOrOff) { 
     self.onCount += 1; 
    }else{ 
     self.onCount -= 1; 
    } 
    NSLog(@"%ld",self.onCount); 
    if (self.onCount == 5) { 
     [sender.selectedCells.lastObject setState:0]; 
     self.onCount -= 1; 
    }  
} 

При попытке выбрать кнопку 5-она будет мигать, но затем погаснуть. Это может быть проблемой в зависимости от того, как вы используете состояние этих кнопок. Я просто вошел их с помощью этого метода:

-(IBAction)checkMatrix:(id)sender { 
    NSIndexSet *indxs = [self.mat.cells indexesOfObjectsPassingTest:^BOOL(NSButtonCell *cell, NSUInteger idx, BOOL *stop) { 
     return cell.state == NSOnState; 
    }]; 
    NSLog(@"%@",indxs); 
} 

После Edit: я не нравлюсь, как мой первый метод прошил кнопку на короткое время перед включением его снова при попытке нажать на кнопку 5-е. Я нашел то, что я думаю, что это лучшее решение, которое включает в себя переопределение MouseDown в матрице подкласса (если вы хотите попробовать это, вы должны удалить заявления SetAction и setTarget и удалить метод ButtonClick):

-(void)mouseDown:(NSEvent *) event { 
    NSPoint matPoint = [self convertPoint:event.locationInWindow fromView:nil]; 
    NSInteger row; 
    NSInteger column; 
    [self getRow:&row column:&column forPoint:matPoint]; 
    NSButtonCell *cell = [self cellAtRow:row column:column]; 
    if (self.onCount < 4 && cell.state == NSOffState) { 
     cell.state = NSOnState; 
     self.onCount += 1; 
    }else if (cell.state == NSOnState) { 
     cell.state = NSOffState; 
     self.onCount -= 1; 
    } 
} 
+0

Отлично; это, безусловно, путь, большое спасибо. – trojanfoe

+0

@trojanfoe: меня не устраивает метод, который я использовал для ограничения количества кнопок, которые могут находиться в состоянии включения, поэтому я придумал то, что, по моему мнению, является лучшим решением. См. Мой отредактированный ответ. – rdelmar

+0

Не беспокойтесь, я все равно использовал другой код подсчета, отключив невыделенные кнопки, когда выбрано 4. Ключом к вашему ответу является использование использования целевого метода и выяснение того, какая кнопка была нажата. – trojanfoe