2011-02-23 2 views
1

텍스트 필드와 두 개의 버튼이 있습니다. 사용자는 텍스트 필드 편집이 끝나면 반환을 누른 다음 조건에 따라 버튼 중 하나 또는 다른 버튼을 다시 활성화하기 위해 돌아올 수 있어야합니다. 버튼을 활성화하기 위해 돌아올 수 있음을 사용자에게 분명히하기 위해, 나는 일시적으로 반환 버튼을 선택한 버튼의 주요 키로 할당합니다. 그러면 키가 파란색으로 빛나야합니다. 버튼이 firstResponder을 사임하면 파란색 빛을 계속하지 않도록 선택된 버튼의 동작은 다음 해당하는 키를 노크NSTextField가 키 이벤트를 두 번 캡처합니다.

switch (self.iNavMode) { 
    case kNavModeNeutral: 
     break; 
    case kNavModeSaveAndNew: 
     [self.window makeFirstResponder:self.btnSaveAndNew]; 
     [self.btnSaveAndNew setKeyEquivalent:@"\r"]; 
     break; 
    case kNavModeSaveAndNext: 
     [self.window makeFirstResponder:self.btnSaveAndNext]; 
     [self.btnSaveAndNext setKeyEquivalent:@"\r"]; 
     break; 
    default: 
     break; 
} 

:

텍스트 필드의 전송 액션 선택이 코드를 포함

[self.btnSaveAndNext setKeyEquivalent:@""]; 

사용자가 텍스트 필드를 벗어나서 돌아올 때 반환 키 이벤트가 어떻게 든 두 번 캡처되고 프로그램에서 사용자가 실제로 반환하지 않았더라도 프로그램 자체에서 단추를 활성화합니다.

첫 번째 리턴 키 이벤트를 완전히 포착하고 처리 할 수있는 방법이 있습니까?

+0

IB의 "보내기 작업"메뉴 항목을 변경하는 것으로 바뀝니다. 검사기 팔레트는 효과가 없습니다. 내 행동을 두 번 피하기 위해 수동으로'[self.searchTextField.cell setSendsActionOnEndEditing : NO]'를 호출해야했습니다. – nielsbot

+0

감사합니다. 그건 내 받아 들여진 대답 kludge보다 나은 해결책 일 수 있습니다. – Wienke

답변

1

글쎄, 나는 골치 거리가있다.

부울 속성 shouldSwallowThisReturn을 추가했습니다. 그리고 텍스트 필드의 전송 액션 선택에 yes로이 부울을 설정하는 라인을 추가 :

switch (self.iNavMode) { 
    case kNavModeNeutral: 
     break; 
    case kNavModeSaveAndNew: 
     [self.window makeFirstResponder:self.btnSaveAndNew]; 
     self.shouldSwallowThisReturn = YES; 
     [self.btnSaveAndNew setKeyEquivalent:@"\r"]; 
     break; 
    case kNavModeSaveAndNext: 
     [self.window makeFirstResponder:self.btnSaveAndNext]; 
     self.shouldSwallowThisReturn = YES; 
     [self.btnSaveAndNext setKeyEquivalent:@"\r"]; 
     break; 
    default: 
     break; 
} 

을 내가 선택한 버튼의 행동을 몇 줄 추가 :

if (self.shouldSwallowThisReturn) { 
    self.shouldSwallowThisReturn = NO; 
    return; 
} 
[self.btnSaveAndNext setKeyEquivalent:@""]; 

의 그래서 나머지 버튼의 액션은 사용자가 두 번째로 return 키를 누른 후에 만 ​​실행됩니다.

이 방법이 효과적이지만 좀 더 세련된 솔루션을 선호합니다.

Apple의 이벤트 처리 가이드에 대한 자세한 내용은 무엇이 잘못 되었습니까? 분명히 IB를 사용하여 텍스트 필드에 보낸 작업을 지정하면 사용자가 반환을 누를 때 동작이 설정되지만 그 반환은 등록되지 않습니다 따라서 앱의 performKeyEquivalent 쿼리에 yes로 응답하지 않으므로 앱은 yes로 응답하는 컨트롤을 계속 찾고 있기 때문에 버튼 자체가 호출됩니다.

그래서 내가 정말이 같은 텍스트 필드를 서브 클래스와 키 코드 36 (리턴 키에 대한 코드) 인 경우는 yes를 반환하도록 그 performKeyEquivalent 메소드를 오버라이드 (override)되어 무엇을해야 보인다

- (BOOL) performKeyEquivalent:(NSEvent *)theEvent { 
    printf("\nThe keycode is %d", [theEvent keyCode]); 
    if ([theEvent keyCode] == 36) 
     return YES; 
    else 
     return NO; 
} 

그러나 대상 텍스트 필드에 포커스가 없을 때에도 override 메서드가 호출된다는 것은 발생합니다. 사실, 선택된 버튼이 이미 firstResponder 인 경우에도 호출됩니다. 이제 사용자의 수익은 항상 선점되어 버튼의 액션은 호출되지 않습니다.

은 내가 firstResponder의 신원을 확인하기 위해 재정의 메서드를 수정 :

- (BOOL) performKeyEquivalent:(NSEvent *)theEvent { 
    printf("\nThe keycode is %d", [theEvent keyCode]); 
    if ([theEvent keyCode] == 36) { 
     ThisProject_AppDelegate *appDelegate = [[NSApplication sharedApplication] delegate]; 
     id firstResponder = [appDelegate.windowController.window firstResponder]; 
     if ([firstResponder isKindOfClass:[NSTextView class]]) { 
      printf("\nfirstResp is a field editor, a textview."); 
      if ([firstResponder delegate] == self) { 
       printf("\ntarget textfield is firstResponder."); 
       return YES; 
      } 
     } 
     else if ([firstResponder isKindOfClass:[NSButton class]]) { 
      printf("\nfirstResp is a button."); 
      return YES; 
     } 
    } 
    return NO; 
} 

그것은 firstResponder 상태가 이미이있는 경우 재정이 후 텍스트 필드의 전송 액션의 실행을 라고 밝혀 버튼에 전송되었습니다. 따라서 오버라이드는 도움이되지 않습니다.

현재로서는이 대답의 맨 끝에 kludge가 붙어 있습니다. 하지만 발신 된 이벤트를 가져 오는 데 필요한 몇 가지 방법이 있어야합니다.

+0

StackOverflow 레프리처는이 질문에 대한 결론을 제안합니다. 나는 사실이 BOOL shouldSwallowThisRotturn kludge가 잘 작동하고 나에게 많은 통제를 주었기 때문에이 대답을 받아 들였습니다. – Wienke

관련 문제