Обработка ключевых событий
Когда пользователь нажимает клавишу на клавиатуре или нажимает несколько клавиш одновременно, система OS X генерирует ключевые события. Когда больше чем одна клавиша нажата, один или больше тех ключей изменяет значение нажатой «основной» клавиши. Обычно используемыми модифицирующими клавишами является Команда, Управление, Опция (Высокий звук) и клавиши Shift. В определенных контекстах и комбинациях, нажатия клавиш представляют команды операционной системе или frontmost приложению и не символам, которые будут вставлены в текст.
В этой главе рассматриваются, как Вы обрабатываете ключевые события, особенно ключевые вниз события.
Обзор ключевых событий
Существенные факты о ключевых событиях, как представлено в Ключевых событиях и Пути Ключевых событий, являются следующим:
Ключевые события имеют три определенных типа (
NSEventType
), каждый из которых связан сNSResponder
метод:Постоянный тип события
Метод события
flagsChanged:
метод может быть полезен для обнаружения нажатия модифицирующих клавиш без любой другой клавиши, нажатой одновременно. Например, если пользователь нажимает функциональную клавишу отдельно, Ваш объект респондента может обнаружить это в своей реализацииflagsChanged:
.Большинство ключевых событий — т.е. те, которые представляют символы, которые будут вставлены как текст — диспетчеризируется
NSWindow
объект связался с ключевым окном первому респонденту.Если первый респондент не обрабатывает событие, оно передает событие цепочка респондента (см. Цепочку Респондента).
Путь поставки ключевого события варьируется согласно тому, представляет ли событие символ, ключевой эквивалент, действие клавиатуры или команду управления интерфейсом клавиатуры. Глобальный объект приложения (
NSApp
) сначала ищет ключевые эквиваленты и затем команды управления интерфейсом клавиатуры и обрабатывает их особенно (см. Путь Ключевых событий для подробных данных). Если событие не имеет ни один их, оно диспетчеризирует егоNSWindow
объект, представляющий ключевое окно, поочередно диспетчеризирующее событие первому респонденту в akeyDown:
сообщение.Объект респондента определяет то, что ключевое событие представляет и обрабатывает его соответственно. В этой точке ключевое событие могло представлять любую из следующих вещей:
Действие клавиатуры, которое является сочетанием клавиш или сочетанием клавиш, связанным с селектором сообщения действия в словаре привязок клавиш (см. Привязки клавиш).
Специализированная команда или действие (одно не использование словаря привязок клавиш)
Символ или символы для вставки в текст
Посмотрите Переопределение keyDown: Метод для получения дополнительной информации.
Как с сообщениями ключевого события, от сообщения действия клавиатуры отказываются цепочка респондента, если первый респондент не обрабатывает его.
Переопределение keyDown: Метод
Большая часть респондента возражает (такие как пользовательские представления), обрабатывают ключевые события путем переопределения keyDown:
метод, объявленный NSResponder
. Объект может обработать событие всегда, это считает целесообразным. Текстовый объект обычно интерпретирует сообщение как запрос для вставки текста, в то время как рисованного объект мог бы только интересоваться несколькими ключами, теми, которые Удаляют и клавиши со стрелками как команды, чтобы удалить и переместить выбранные пункты. Как с событиями от нажатия мыши, объект респондента часто хочет запросить переданный - в NSEvent
объект узнать больше о событии и получить данные это должно обработать его. Некоторые более полезные NSEvent
методы для ключевых событий являются следующим:
characters
иcharactersIgnoringModifiers
— Респондент может извлечь данные символа Unicode, связанные с событием, и вставить его как текст или интерпретировать его как команды.charactersIgnoringModifiers
метод игнорирует любое нажатие клавиши модификатора (за исключением Сдвига) при возврате символьных данных. Обратите внимание на то, что оба имен методов являются множественным числом, потому что нажатие клавиши может произвести больше чем один символ (например, «Е» составлен из и ‘' ‘).modifierFlags
— Используя этот метод респондент может определить, были ли нажаты какие-либо модифицирующие клавиши.isARepeat
— Этот метод говорит респонденту, была ли та же клавиша нажата быстро по очереди.
В реализации a keyDown:
метод, респондент может извлечь символьные данные, содержавшие связанным NSEvent
возразите и вставьте его в отображаемый текст; или это может интерпретировать символьные данные как сочетание клавиш или сочетание клавиш, или связывающееся с действием клавиатуры или запрашивающее некоторое специализированное поведение. Однако Набор Приложения обеспечивает некоторые удобные ярлыки для того, чтобы сделать это, описанное ниже.
Обработка действий клавиатуры и вставки текста
Респондент возражает, что соглашение с текстом, таким как текст представления, должно быть подготовлено обработать ключевые события, которые могут или быть символами для вставки или действия клавиатуры. Как отмечено по Пути Ключевых событий, действия клавиатуры являются специальным видом сообщения действия, зависящего от механизма привязок клавиш, связывающего определенные нажатия клавиш (например, Управление-e) к определенным командам, связанным с текстом (например, переместите точку вставки до конца текущей строки). Эти команды реализованы в методах, определенных NSResponder
дать функциональные интерпретации на представление тех физических нажатий клавиш.
В обработке ключевого события в keyDown:
, объект представления, ожидающий вставлять текст сначала, определяет ли символ или символы NSEvent
объект представляет действие клавиатуры. Если они делают, это отправляет связанное сообщение действия; если они не делают, это вставляет символы как текст. В частности представление может сделать одну из двух вещей в его реализации:
Это может извлечь символы объекта-события с помощью
characters
методNSEvent
и интерпретируйте их, чтобы видеть, связаны ли они с известным действием клавиатуры. Если они, это вызывает метод соответствующих мер сам по себе или суперпредставление. Этому подходу обескураживают.Это может передать событие системе управления ввода текста Какао путем вызова
NSResponder
методinterpretKeyEvents:
. Входная система управления проверяет нажатую клавишу по записям во всех соответствующих словарях привязки клавиш и, если существует соответствие, отправляет adoCommandBySelector:
обменивайтесь сообщениями назад к представлению. Иначе, это отправляетinsertText:
обменивайтесь сообщениями назад к представлению, и представление реализует этот метод, чтобы извлечь и вывести на экран текст.
Перечисление 5-1 показывает, как второй подход мог бы посмотреть в коде.
Перечисление 5-1 Используя входную систему управления для интерпретации ключевого события
- (void)keyDown:(NSEvent *)theEvent { |
[self interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; |
} |
// The following action methods are declared in NSResponder.h |
- (void)insertTab:(id)sender { |
if ([[self window] firstResponder] == self) { |
[[self window] selectNextKeyView:self]; |
} |
} |
- (void)insertBacktab:(id)sender { |
if ([[self window] firstResponder] == self) { |
[[self window] selectPreviousKeyView:self]; |
} |
} |
- (void)insertText:(id)string { |
[super insertText:string]; // have superclass insert it |
} |
Обратите внимание на то, что этот пример включает переопределение insertText:
это просто вызывает реализацию суперкласса. Это сделано для разъяснения роли менеджера по вводу, но не действительно необходимо. Значение по умолчанию (NSResponder
) реализация doCommandBySelector:
определяет, реагирует ли представление на селектор действия клавиатуры и, если представление действительно отвечает, это вызывает метод действия; если представление не отвечает, doCommandBySelector:
отправляется следующему респонденту (и т.д. цепочка респондента). Поэтому представление должно только реализовать методы действия, соответствующие действиям, которые оно хочет обработать. Другая импликация поведения входного менеджера - то, что, если словарь привязок клавиш соответствует физическое нажатие клавиши действию клавиатуры, объект респондента просто должен переопределить связанный метод действия обработать то нажатие клавиши. Например, для обработки привязки по умолчанию Клавиши выхода респондент переопределил бы cancelOperation:
метод NSResponder
.
Рассматриваемый вопрос суперпредставления, обрабатывающего сообщение действия клавиатуры, инициируемое подпредставлением, является путем NSScrollView
возразите командам страницы вниз дескрипторов. Этот объект представления прокрутки является составным объектом, состоящим из представления документа, представления клипа ( NSClipView
объект) и скроллер ( NSScroller
объект). Поскольку это - содержание или координирование объекта, NSScrollView
объект является суперпредставлением всех других объектов в этой группировке. Теперь скажите, что Ваше пользовательское представление является представлением документа представления прокрутки. Если Вы реализуете keyDown:
отправить interpretKeyEvents:
менеджеру по вводу, но не реализуют scrollPageDown:
метод действия, представление документа будет все еще прокручено в представлении прокрутки, когда пользователь нажмет клавишу Page Down (или независимо от того, что привязка клавиш имеет силу для той функции). Это происходит, потому что каждый следующий респондент в цепочке респондента запрашивается, чтобы видеть, отвечает ли она на scrollPageDown:
. NSScrollView
класс обеспечивает реализацию по умолчанию, таким образом, вызывается эта реализация.
Приложения другой, что те, которые имеют дело с текстом, могут использовать входную систему управления для их преимущества. Например, пользовательское представление в приложении получения могло бы использовать клавиши со стрелками, чтобы "пошагово переместить” графические объекты точные расстояния. В стандартном словаре привязок клавиш клавиши со стрелками связываются с moveUp:
, moveDown:
, moveLeft:
, и moveRight:
методы NSResponder
. Так кодируйте подобный показанному в Перечислении 5-2, работал бы для пошагового перемещения графических объектов вокруг.
Перечисление 5-2 , Обрабатывающее символы клавиши со стрелкой с помощью входной системы управления
- (void)keyDown:(NSEvent *)theEvent { |
// Arrow keys are associated with the numeric keypad |
if ([theEvent modifierFlags] & NSNumericPadKeyMask) { |
[self interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; |
} else { |
[super keyDown:theEvent]; |
} |
} |
-(IBAction)moveUp:(id)sender |
{ |
[self offsetLocationByX:0 andY: 10.0]; |
[[self window] invalidateCursorRectsForView:self]; |
} |
-(IBAction)moveDown:(id)sender |
{ |
[self offsetLocationByX:0 andY:-10.0]; |
[[self window] invalidateCursorRectsForView:self]; |
} |
-(IBAction)moveLeft:(id)sender |
{ |
[self offsetLocationByX:-10.0 andY:0.0]; |
[[self window] invalidateCursorRectsForView:self]; |
} |
-(IBAction)moveRight:(id)sender |
{ |
[self offsetLocationByX:10.0 andY:0.0]; |
[[self window] invalidateCursorRectsForView:self]; |
} |
В большинстве экземпляров, interpretKeyEvents:
подход предпочтителен для интерпретирования - самостоятельно приближаются. Эта рекомендация является особенно истиной для тех пользовательских представлений в приложениях, таких как текстовые процессоры и графические редакторы, делающие львиную долю работы. Основной фактор, одобряющий использование системы управления ввода текста, - то, что с ним Вы не должны соединять функцию проводами к физическому ключу. Что, если пользователь использует портативный компьютер, испытывающий недостаток в функциональной клавише, соединенной проводами приложением? Лучше, более гибкий подход должен указать альтернативные привязки клавиш в словаре. Другое преимущество системы управления ввода текста состоит в том, что она позволяет ключевым событиям интерпретироваться как текст, не непосредственно доступный на клавиатуре, такой как Кандзи и некоторые символы с диакритикой.
Особенно интерпретация нажатий клавиш
Несмотря на то, что использование системы управления ввода текста выгодно, можно интерпретировать физические ключи сами в keyDown:
и обработайте их специализированным способом. NSEvent
класс объявляет десятки констант, идентифицирующих определенные ключи или ключевым символом или ключевой функцией; Константы в справочной документации для того класса описывают эти константы. Перечисление 5-3 показывает выборку.
Константы ключа Listing 5-3 Some определяются NSResponder
enum { |
NSUpArrowFunctionKey = 0xF700, |
NSDownArrowFunctionKey = 0xF701, |
NSLeftArrowFunctionKey = 0xF702, |
NSRightArrowFunctionKey = 0xF703, |
NSF1FunctionKey = 0xF704, |
NSF2FunctionKey = 0xF705, |
NSF3FunctionKey = 0xF706, |
// other constants here |
NSUndoFunctionKey = 0xF743, |
NSRedoFunctionKey = 0xF744, |
NSFindFunctionKey = 0xF745, |
NSHelpFunctionKey = 0xF746, |
NSModeSwitchFunctionKey = 0xF747 |
}; |
Кроме того, текстовая система определяет константы, представляющие обычно используемые символы Unicode, такие как вкладка, удалите, и возврат каретки. Для списка этих констант посмотрите Константы в Ссылке класса NSText.
В Вашей реализации keyDown:
можно сравнить одну из этих констант к символьным данным объекта ключевого события определить, была ли определенная клавиша нажата и затем действие соответственно. Поскольку можно вспомнить, characters
или charactersIgnoringModifiers
методы возвращаются NSString
объект для значения ключа вместо символа, потому что нажатие клавиши могло бы генерировать многократные символы. (Фактически, эти методы могли даже возвратить пустую строку, если мертвая клавиша — нажата клавиша без символа, отображенного на ней —.), Если Ваша реализация keyDown:
обрабатывает односимвольное значение ключа, такое как клавиша со стрелкой, можно исследовать длину возвращаемой строки и, если это - отдельный символ, доступ тот символ с помощью NSString
метод characterAtIndex:
с индексом 0. Тогда тест, что символ против одного из NSResponder
константы.
Перечисление 5-4 показывает, как Вы могли бы выполнить тот же графический объект, «пошагово перемещающий», как сделано в Перечислении 5-2, но на сей раз сам объект респондента определяет, была ли нажата клавиша со стрелкой.
Перечисление 5-4 , Обрабатывающее символы клавиши со стрелкой путем интерпретации физического ключа
- (void)keyDown:(NSEvent *)theEvent { |
if ([theEvent modifierFlags] & NSNumericPadKeyMask) { // arrow keys have this mask |
NSString *theArrow = [theEvent charactersIgnoringModifiers]; |
unichar keyChar = 0; |
if ( [theArrow length] == 0 ) |
return; // reject dead keys |
if ( [theArrow length] == 1 ) { |
keyChar = [theArrow characterAtIndex:0]; |
if ( keyChar == NSLeftArrowFunctionKey ) { |
[self offsetLocationByX:-10.0 andY:0.0]; |
[[self window] invalidateCursorRectsForView:self]; |
return; |
} |
if ( keyChar == NSRightArrowFunctionKey ) { |
[self offsetLocationByX:10.0 andY:0.0]; |
[[self window] invalidateCursorRectsForView:self]; |
return; |
} |
if ( keyChar == NSUpArrowFunctionKey ) { |
[self offsetLocationByX:0 andY: 10.0]; |
[[self window] invalidateCursorRectsForView:self]; |
return; |
} |
if ( keyChar == NSDownArrowFunctionKey ) { |
[self offsetLocationByX:0 andY:-10.0]; |
[[self window] invalidateCursorRectsForView:self]; |
return; |
} |
[super keyDown:theEvent]; |
} |
} |
[super keyDown:theEvent]; |
} |
Можно также преобразовать NSResponder
постоянный к строке возражают и затем сравнивают тот объект со значением, возвращенным characters
или charactersIgnoringModifiers
, как в этом примере:
unichar la = NSLeftArrowFunctionKey; |
NSString *laStr = [[[NSString alloc] initWithCharacters:&la length:1] autorelease]; |
if ([theArrow isEqual:laStr]) { |
[self offsetLocationByX:-10.0 andY:0.0]; |
[[self window] invalidateCursorRectsForView:self]; |
return; |
} |
Однако этот подход является более интенсивно использующим память.
Обработка ключевых эквивалентов
Ключевой эквивалент является символом, связанным с некоторым представлением в окне. Этот обязательные причины, просматривающие для выполнения указанного действия, когда пользователь вводит тот символ, обычно при нажатии модифицирующей клавиши (в большинстве случаев Командная клавиша). Ключевой эквивалент должен быть символом, который может быть введен без модифицирующих клавиш, или со Сдвигом только.
Приложение направляет ключевое эквивалентное событие путем отправки ему сначала вниз иерархии представления окна. Глобальная переменная NSApplication
возразите диспетчеризирует события, которые это распознает как потенциальные ключевые эквиваленты (на основе присутствия флагов модификатора) в sendEvent:
метод. Это отправляет a performKeyEquivalent:
обменивайтесь сообщениями к ключу NSWindow
объект. Этот объект передает ключевые эквиваленты вниз его иерархия представления путем вызова NSView
реализация по умолчанию performKeyEquivalent:
, который передает сообщение к каждому из его подпредставлений (включая контекстный и всплывающие меню), пока каждый не отвечает YES
; если ни один не делает, это возвращается NO
. Если никакой объект в иерархии представления не обрабатывает ключевой эквивалент, NSApp
тогда отправляет performKeyEquivalent:
к меню в строке меню. NSWindow
подклассы отговорены переопределить performKeyEquivalent:
.
Некоторые классы Какао, такой как NSButton
, NSMenu
, NSMatrix
, и NSSavePanel
, обеспечьте реализации по умолчанию performKeyEquivalent:
. Например, можно установить клавишу Return как ключевой эквивалент NSButton
возразите и, когда эта клавиша нажата, действия кнопки, как будто по ней щелкнули. Однако подклассы других классов Набора Приложения (включая пользовательские представления) должны обеспечить свои собственные реализации performKeyEquivalent:
. Реализация должна извлечь символы для ключевого эквивалента от переданного - в NSEvent
объект с помощью charactersIgnoringModifiers
метод и затем исследует их, чтобы определить, являются ли они ключевым эквивалентом, он распознает. Это обрабатывает ключевой эквивалент очень, как это обработало бы ключевое событие в keyDown:
(см. Переопределение keyDown: Метод). После обработки ключевого эквивалента должна возвратиться реализация YES
. Если это не обрабатывает ключевой эквивалент, это должно или вызвать реализацию суперкласса performKeyEquivalent:
или (если Вы знаете, суперкласс не обрабатывает ключевой эквивалент), возврат NO
указать, что ключевой эквивалент должен быть передан далее вниз иерархия представления или к меню в строке меню.
Управление интерфейсом клавиатуры
Архитектура отгрузки события Какао обрабатывает определенные ключевые события как команды, чтобы переместить фокус управления в различный объект пользовательского интерфейса в окне, моделировать щелчок мышью по объекту, отклонить модальные окна и сделать выборы в объектах, позволяющих выборы. Эту возможность вызывают управлением интерфейсом клавиатуры. Большинство объектов пользовательского интерфейса, вовлеченных в управление интерфейсом клавиатуры, NSControl
объекты, но объекты, которые не являются средствами управления, могут участвовать также. Когда объект имеет фокус управления, Набор Приложения рисует голубое ключевое фокусирующее кольцо вокруг границы объекта. Если полный доступ клавиатуры включен, ключи, перечисленные в Таблице 5-1, имеют установленный эффект.
Ключ | Эффект |
---|---|
Вкладка | Переместитесь в следующее ключевое представление. |
Shift-Tab | Переместитесь в предыдущее ключевое представление. |
Пространство | Выберите, как щелчком мышью во флажке (например), или состоянием переключателя. В списках выбора, выбирает или отменяет выбор выделенного элемента. |
Клавиши со стрелками | Переместитесь в составном представлении, такой как |
Вкладка управления (Вкладка сдвига управления) | Перейдите к следующему (предыдущему) ключевому представлению от представлений, где символы табуляции имеют другое значение (например, |
Опция или сдвиг | Расширьте выбор, не влияя на другие выбранные пункты. |
Некоторые объекты, найденные на палитрах Interface Builder, не участвуют в управлении интерфейсом клавиатуры, такой как NSImageView
, WebView
, и PDFView
объекты.
В дополнение к ключевому циклу представления окно может иметь ячейку кнопки по умолчанию, использующую Возврат (или Войдите), ключ как его ключевой эквивалент. Программно, можно отправить setDefaultButtonCell:
к NSWindow
возразите для установки этой ячейки кнопки; можно также установить его в Интерфейсном Разработчике путем устанавливания ключа ячейки кнопки, эквивалентного‘\r
’в области Attributes окна Get Info. Ячейка кнопки по умолчанию рисует себя как фокальный элемент для управления интерфейсом клавиатуры, если другая ячейка кнопки не фокусируется на. В этом случае это временно рисует себя как нормальный и отключает его ключевой эквивалент. Клавиша выхода является другим ключом по умолчанию для управления интерфейсом клавиатуры в окне; это сразу прерывает модальный цикл.
Объекты пользовательского интерфейса, соединяющиеся вместе в окне, составляют ключевой цикл представления окна. Ключевой цикл представления является последовательностью NSView
объекты соединились друг с другом через их nextKeyView
свойство ( previousKeyView
свойство при входе в обратное направление). Последнее представление в этой последовательности «циклы» назад к первому представлению. По умолчанию, NSWindow
присваивает начального первого респондента и создает ключевой цикл представления с объектами, которые он находит. Если Вы хотите большее управление ключевым циклом представления, необходимо установить его использующий Интерфейсного Разработчика. Посмотрите страницы справки для Интерфейсного Разработчика для подробных данных процедуры.
Для его экземпляров для участия в циклах ключевого представления должно возвратиться пользовательское представление YES
от acceptsFirstResponder
. Путем выполнения так, это влияет на значение, возвращенное canBecomeKeyView
метод. acceptsFirstResponder
метод управляет, принимает ли респондент первое состояние респондента, когда его окно спрашивает его к (т.е. когда makeFirstResponder: вызывается с респондентом как параметр). canBecomeKeyView
метод управляет, позволяет ли Набор Приложения снабжать вкладками к представлению. Это вызывает acceptsFirstResponder
, но это также проверяет на другую информацию прежде, чем определить значение для возврата, такой как, скрыто ли представление и идет ли полный доступ клавиатуры. canBecomeKeyView
метод редко переопределяется в то время как acceptsFirstResponder
часто переопределяется.
NSView
и NSWindow
классы определяют много методов для того, чтобы настроить и пересечь ключевой цикл представления программно. Таблица 5-2 перечисляет некоторые более полезные.
| Возвращает следующие и предыдущие объекты представления в ключевом цикле представления. |
| Устанавливает следующее ключевое представление в цикле. |
| Ищет иерархию представления кандидата затем (предыдущее) ключевое представление и, если это находит один, делает его первым респондентом. |
| Возвраты, может ли получатель стать ключевым представлением. |
| Возвращает самый близкий объект представления в ключевом цикле представления, следующем за получателем и принимающем первое состояние респондента. |
Код в Перечислении 5-5 иллюстрирует, как можно было бы использовать некоторые из этих методов для управления циклом ключевого представления.
Перечисление 5-5 , Управляющее циклом ключевого представления
- (void)textDidEndEditing:(NSNotification *)notification { |
NSTextView *text = [notification object]; |
unsigned whyEnd = [[[notification userInfo] objectForKey:@"NSTextMovement"] unsignedIntValue]; |
NSTextView *newKeyView = text; |
// Unscroll the previous text. |
[text scrollRangeToVisible:NSMakeRange(0, 0)]; |
if (whyEnd == NSTabTextMovement) { |
newKeyView = (NSTextView *)[text nextKeyView]; |
} else if (whyEnd == NSBacktabTextMovement) { |
newKeyView = (NSTextView *)[text previousKeyView]; |
} |
// Set the new key view and select its whole contents. |
[[text window] makeFirstResponder:newKeyView]; |
[newKeyView setSelectedRange:NSMakeRange(0, [[newKeyView textStorage] length])]; |
} |