Получение пользовательского NSCell с экземпляром NSButtonCell для обработки событий щелчка мыши / мыши - PullRequest
1 голос
/ 10 июня 2010

ОК, я действительно в тупике. Я хочу сделать флажок с NSTextFieldCell объединены вместе. Важно, чтобы флажок горит, если мышь попадает в поле, а не текст. Я достиг это более или менее, но проблема заключается в получении события мыши, потому что Я нажимаю один флажок подряд, но ВСЕ они превращаются в NSOnState. я покажет, что я сделал, и мои различные неудачные попытки, чтобы заставить это работать.

Итак, вот как я это сделал до сих пор:

Заголовок:

@interface MyCheckboxCellToo : NSTextFieldCell {
   NSButtonCell *_checkboxCell;
}

реализация:

- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView {
    NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil];
    NSLog(@"%@", NSStringFromPoint(point));

    NSRect checkFrame;
    NSDivideRect(cellFrame, &checkFrame, &cellFrame, cellFrame.size.height/*3 + [[_checkboxCell image] size].width*/, NSMinXEdge);

    if (NSMouseInRect(point, checkFrame, [controlView isFlipped])) {
        // the checkbox, or the small region around it, was hit. so let's flip the state
        NSCellStateValue checkState = ([_checkboxCell state] == NSOnState) ? NSOffState:NSOnState;
        [self setState:checkState];
        [_checkboxCell setState:checkState];
        [controlView setNeedsDisplay:YES];
        return NSCellHitTrackableArea;
    }        
    return [super hitTestForEvent:event inRect:cellFrame ofView:controlView];    
}

Я знаю, что, вероятно, не должен был делать:

   [self setState:checkState];
   [_checkboxCell setState:checkState];
   [controlView setNeedsDisplay:YES];

там ... потому что результат в том, что каждый флажок в каждом идет к NSOnState. Это потому, что клетки используются повторно? Почему у ImageAndTextCell могут быть разные изображения в одном и том же виде таблицы? Как мне обработать событие мыши?

Я пытался:

- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame
ofView:(NSView *)controlView untilMouseUp:(BOOL)untilMouseUp {
   NSLog(@"%s %@", _cmd, theEvent);
   return [_checkboxCell trackMouse:theEvent inRect:cellFrame
ofView:controlView untilMouseUp:untilMouseUp];
//    return YES;
//    return [super trackMouse:theEvent inRect:cellFrame
ofView:controlView untilMouseUp:untilMouseUp];
}

- (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView {
   NSLog(@"%s %@", _cmd, NSStringFromPoint(startPoint));
   return [super startTrackingAt:startPoint inView:controlView];
}

- (BOOL)continueTracking:(NSPoint)lastPoint at:(NSPoint)currentPoint
inView:(NSView *)controlView {
   NSLog(@"%s %@", _cmd, NSStringFromPoint(currentPoint));
   return [super continueTracking:lastPoint at:currentPoint
inView:controlView];
}

- (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint
inView:(NSView *)controlView mouseIsUp:(BOOL)flag {
   NSLog(@"%s %d %@", _cmd, flag, NSStringFromPoint(stopPoint));
}

trackMouse: ... ДОЛЖЕН вызываться

но

startTrackingAt: ..., continueTracking: ... и stopTracking: .... DO НЕ вызывается, когда я нажимаю на флажок "область попадания"

в trackMouse: ... я пробовал

return [_checkboxCell trackMouse:theEvent inRect:cellFrame ofView:controlView untilMouseUp:untilMouseUp];

и

return [super trackMouse:theEvent inRect:cellFrame ofView:controlView untilMouseUp:untilMouseUp];

и ни один из них не приводит к тому, что событие мыши обрабатывается флажком.

Как мне заставить этот единственный флажок перейти в NSOnState? Я знаю, что я красивая закрыть, но после большого количества чтения документов и поиска в Google у меня нет удалось решить эту проблему.

предложения и комментарии приветствуются ..


Хорошо, еще немного, чтобы показать создание и уничтожение объекта.

- (id)init {
    if ((self = [super init])) {
        _checkboxCell = [[NSButtonCell alloc] init];
        [_checkboxCell setButtonType:NSSwitchButton];
        [_checkboxCell setTitle:@""];
        [_checkboxCell setTarget:self];
        [_checkboxCell setImagePosition:NSImageLeft];
        [_checkboxCell setControlSize:NSRegularControlSize];

    }
    return self;
}

- copyWithZone:(NSZone *)zone {
    MyCheckboxCellToo *cell = (MyCheckboxCellToo *)[super copyWithZone:zone];
    cell->_checkboxCell = [_checkboxCell copyWithZone:zone];
    return cell;
}

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

Ответы [ 3 ]

0 голосов
/ 02 июля 2010

Хорошо, это то, что, казалось, решило мою проблему, более или менее.

в hitForTestEvent: ...

вместо

    if (NSMouseInRect(point, checkFrame, [controlView isFlipped])) {
    // the checkbox, or the small region around it, was hit. so let's flip the state
    NSCellStateValue checkState = ([_checkboxCell state] == NSOnState) ? NSOffState:NSOnState;
    [self setState:checkState];
    [_checkboxCell setState:checkState];
    [controlView setNeedsDisplay:YES];
    return NSCellHitTrackableArea;
}        

должно быть:

    if (NSMouseInRect(point, checkFrame, [controlView isFlipped])) {
    [_checkboxCell setState:![_checkboxCell state]];
    return NSCellHitTrackableArea;
}        

У меня все еще есть некоторые проблемы, когда если я нажимаю на зону попадания флажка в определенном месте, она не регистрируется, но более или менее это работает.

0 голосов
/ 01 марта 2011

Я создал пользовательский класс ячейки, который является подклассом NSButtonCell вместо NSTextFieldCell. Возвращает 0 в hitTestForEvent: inRect: ofView: если щелчок отсутствует на флажке.

Когда пользователь нажимает на флажок, в браузере делегата NSBrowser: setObjectValue: forItem: Я получаю NSBoolean и устанавливаю «флажок» ivar моего соответствующего объекта «узла» равным этому NSBoolean.

В браузере делегата NSBrowser: willDisplayCell: atRow: column: метод, который я вызываю [browser itemAtIndex:], чтобы получить мой «узел», и вызываю метод setState: ячейки с «проверенным» иваром узла.

Посмотрите пример проекта Xcode "ComplexBrowser" для примера кода в делегате браузера.

Что бы вы ни делали, я не рекомендую создавать подклассы NSBrowserCell. Это был большой тупик для меня.

ОБНОВЛЕНИЕ 30 августа 2011: Это не работает в 10.5. Тьфу. Я вернулся на круги своя.

0 голосов
/ 11 июня 2010

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

Я знаю, что, вероятно, не должен был делать:

[self setState:checkState];
[_checkboxCell setState:checkState];
[controlView setNeedsDisplay:YES];

там ... потому что результат в том, что КАЖДЫЙ флажок в каждом идет к NSOnState. Это потому, что клетки используются повторно?

Они используются повторно в отличном от того, как UITableView использует UITableViewCells.

(Я заметил, что вы пометили вопрос «NSTableViewCell». В AppKit такого класса нет).

Почему у ImageAndTextCell могут быть разные изображения в одном и том же виде таблицы?

Ответ на оба вопроса один и тот же.

В то время как UITableView использует одну ячейку для каждой строки и хранит столько же ячеек, сколько строк на экране, NSTableView использует одну ячейку для каждого столбца.

Каждый столбец существует как объект NSTableColumn, и каждый NSTableColumn имеет ровно одну ячейку *. Табличное представление устанавливает значение объекта ячейки равным любому значению, которое вы указали для этого пересечения столбец-строка, а затем велит ячейке рисовать в соответствующем месте в пределах ее границ. Он будет делать то же самое с той же ячейкой для этого столбца для каждой строки.

(Здесь есть исключения, поскольку Apple добавила возможность использовать другую ячейку для определенных строк и поскольку они добавили групповые строки, которые не имеют столбцов и используют другую ячейку. Однако фундаментальный механизм тот же.)

Мне очень жаль, что я не могу помочь вам на пути к решению (кроме моего предложения "просто сделай их отдельными колонками"), но я надеюсь, что это, по крайней мере, поможет тебе в этом.

* У него тоже есть ячейка заголовка, но здесь это не считается. «Ровно одна ячейка», о которой я говорю, это ячейка данных.

...