Захват клавиш вверх и вниз, нажатых в NSTextField

Я написал приложение Agent Cocoa, в котором TextField находится в меню значка состояния. Меню значков отображается следующим образом:


(источник: ifotos .pl)

Степпер увеличивает или уменьшает значение на 5. Целью текстового поля является нажатие клавиш вверх или вниз, что приводит к тому же результату, что и значение увеличивается или уменьшается на 5.

Я обнаружил, что следующий код должен использоваться - (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector протокола NSControlTextEditingDelegate.

Проблема, с которой я сейчас сталкиваюсь, заключается в том, как реализовать код. Мой обычный подход — использовать sth.delegate = self;. Я попытался найти ответ, но ответы состояли из использования control:textView:.... Я не смог научиться использовать метод делегирования даже после дальнейших исследований.

Заранее спасибо!


person radex    schedule 11.07.2011    source источник


Ответы (3)


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

- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector

Этот метод будет вызываться всякий раз, когда открывается редактор полей* для текстовое поле запрашивается для выполнения одного из NSResponder сообщения о действиях. Редактор поля спрашивает своего делегата, которым является текстовое поле, что оно должно делать, а поле, в свою очередь, спрашивает своего делегата, который является вашим объектом.

Аргумент commandSelector содержит имя сообщения о действии. Поэтому вы можете проверить интересующие вас сообщения (в данном случае moveUp: и moveDown:) и перехватить их. Вы выполняете любые действия, которые вам нравятся, и запрещаете редактору поля или текстовому полю воздействовать на сообщение.

- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor 
  doCommandBySelector:(SEL)commandSelector {
    if( commandSelector == @selector(moveUp:) ){
        // Your increment code
        return YES;    // We handled this command; don't pass it on
    }
    if( commandSelector == @selector(moveDown:) ){
        // Your decrement code
        return YES;
    }

    return NO;    // Default handling of the command

} 

*Кратко, NSTextView, который обрабатывает ввод от имени текстового поля, когда поле активно.

person jscs    schedule 11.07.2011
comment
Radex, надеюсь, это более понятно, чем документы; дайте мне знать, если вам нужны разъяснения. - person jscs; 12.07.2011
comment
Да, да, да! Спасибо. Это намного понятнее, чем документы. Документация Apple настолько запутана, что я даже не подумал, что это настолько очевидно :) - person radex; 12.07.2011

Попробуйте переопределить сообщение NSResponder следующим образом:

- (BOOL)performKeyEquivalent:(NSEvent *)theEvent{
    switch ([[theEvent charactersIgnoringModifiers] characterAtIndex:0]) {
        case NSUpArrowFunctionKey:
            // Increase by 5 here
            return YES;
            break;
        case NSDownArrowFunctionKey:;
            // Decrease by 5 here
            return YES;
            break;
        default:
            break;
    }
    return [super performKeyEquivalent:theEvent];
}
person ZhangChn    schedule 11.07.2011
comment
Одна странная вещь, которую я обнаружил в этом методе: PerformKeyEquivalent не ограничивается цепочкой ответчика. Любое представление, которое реализует это, может быть вызвано, независимо от того, имеет ли оно фокус, и если оно возвращает YES, оно может помешать текущему первому ответчику получить ключевое событие. Если вы используете это для перехвата нажатий клавиш со стрелками в подклассе NSTextField, сначала проверьте, что это текущий первый ответчик: if ( [[self window] firstResponder] != self ) return [super PerformKeyEquivalent:event]; - person davehayden; 26.06.2014

если вы хотите захватить ярлыки, вы также можете использовать такой код:

- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector {

NSEvent *currentEvent = [[NSApplication sharedApplication]currentEvent];
if ((currentEvent.modifierFlags & NSCommandKeyMask) && (currentEvent.keyCode == kVK_Return)) {  //command + enter to confirm
    //do what you want
    return YES;
}
return NO;
}
person holybiner    schedule 05.08.2016