2012-02-05 1 views
5

Мне бы очень хотелось, чтобы мой пользовательский просмотр работал с -moveLeft:, -deleteForward:, -selectAll: и т. Д., Но я также хотел бы передать любые ключи, на которые меня не интересовало движение вверх по цепочке ответчиков. Прямо сейчас я переопределяю -keyDown:, чтобы позвонить [self interpretKeyEvents:[NSArray arrayWithObject:event]];, но это, похоже, запустит все ключевые события, даже те, на которые мой взгляд не отвечает.Показать интерпретироватьKeyEvents: но передать нежелательные в цепочку ответчиков?

Есть ли способ пройти нежелательные события вверх по цепочке, но все же отвечать на -moveLeft: и т. Д.? Или мне нужно реализовать все свои собственные действия в -keyDown:, чтобы я знал, что я сделал и не ответил?

+0

Попробуйте мой [решение] (http://stackoverflow.com/a/23897022/1067147) – WINSergey

ответ

6

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

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

@interface MyTextView : NSTextView { 
    NSEvent* _keyDownEvent; 
} 

@end 

Затем определяют методы вашей точки зрения как так (вывезти сохранить/релиз нежелательной, если вы используете автоматический подсчет ссылок):

@implementation MyTextView 

- (id)initWithFrame:(NSRect)frame { 
    if (self = [super initWithFrame:frame]) { 
     _keyDownEvent = nil; 
    } 

    return self; 
} 

- (void)keyDown:(NSEvent*)event { 
    [_keyDownEvent release]; 
    _keyDownEvent = [event retain]; 
    [super keyDown:event]; 
} 

- (void)doCommandBySelector:(SEL)selector { 
    if (_keyDownEvent && selector == @selector(noop:)) { 
     if ([self nextResponder]) { 
      [[self nextResponder] keyDown:[_keyDownEvent autorelease]]; 
     } else { 
      [_keyDownEvent release]; 
     } 
     _keyDownEvent = nil; 
    } else { 
     [super doCommandBySelector:selector]; 
    } 
} 

- (void)dealloc { 
    [_keyDownEvent release]; 

    [super dealloc]; 
} 

@end 

Вот как я прибыл на это. Когда нажатие клавиши не обрабатывается, вы слышите звуковой сигнал. Итак, я поставил точку останова на NSBeep(), и когда программа сломалась, я выплюнул трассирование в GDB:

#0 0x00007fff96eb1c2d in NSBeep() 
#1 0x00007fff96e6d739 in -[NSResponder doCommandBySelector:]() 
#2 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#3 0x00007fff96fda826 in -[NSWindow doCommandBySelector:]() 
#4 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#5 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#6 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#7 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#8 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#9 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#10 0x00007fff96e6d72b in -[NSResponder doCommandBySelector:]() 
#11 0x00007fff96f486ce in -[NSTextView doCommandBySelector:]() 
#12 0x00007fff96da1c93 in -[NSKeyBindingManager(NSKeyBindingManager_MultiClients) interpretEventAsCommand:forClient:]() 
#13 0x00007fff970f5382 in -[NSTextInputContext handleEvent:]() 
#14 0x00007fff96fbfd2a in -[NSView interpretKeyEvents:]() 
#15 0x00007fff96f38a25 in -[NSTextView keyDown:]() 
#16 0x0000000100012889 in -[MyTextView keyDown:] (self=0x1004763a0, _cmd=0x7fff972b0234, event=0x100197320) at /path/MyTextView.m:24 
#17 0x00007fff96a16b44 in -[NSWindow sendEvent:]() 
#18 0x00007fff969af16d in -[NSApplication sendEvent:]() 
#19 0x00007fff969451f2 in -[NSApplication run]() 
#20 0x00007fff96bc3b88 in NSApplicationMain() 
#21 0x00000001000015e2 in main (argc=3, argv=0x7fff5fbff8f0) at /path/main.m:12 

Что происходит это: Когда ключ вниз событие не используется для ввода текста , команда «noop» отправляется цепочкой ответов. По умолчанию это вызывает звуковой сигнал, когда он падает с цепи ответа. В моем решении подкласс NSTextView ловит команду noop и вместо этого генерирует исходное событие keyDown по цепочке ответов. Тогда ваши NSWindow или другие представления получат любые неиспользуемые события KeyDown как обычно.

3

Это мое быстрое осуществление ответ @ daxnitro, и, кажется, работает:

import Cocoa 

class EditorTextView: NSTextView { 

    private var keyDownEvent: NSEvent? 

    required init?(coder aCoder: NSCoder) { 
     super.init(coder: aCoder) 
    } 

    override init() { 
     super.init() 
    } 

    override init(frame frameRect: NSRect, textContainer aTextContainer: NSTextContainer!) { 
     super.init(frame: frameRect, textContainer: aTextContainer) 
    } 

    override func keyDown(event: NSEvent) { 
     keyDownEvent = event 
     super.keyDown(event) 
    } 

    override func doCommandBySelector(aSelector: Selector) { 
     if aSelector != NSSelectorFromString("noop:") { 
      super.doCommandBySelector(aSelector) 
     } else if keyDownEvent != nil { 
      self.nextResponder?.keyDown(keyDownEvent!) 
     } 
     keyDownEvent = nil 
    } 

} 

 Смежные вопросы

  • Нет связанных вопросов^_^