【问题标题】:NSWindow, press key ENTER: how to limit the key listening to the focused NSControl?NSWindow,按回车键:如何限制按键监听聚焦的NSControl?
【发布时间】:2015-02-03 15:44:07
【问题描述】:

我有一个NSWindow,带有一个主“确定”按钮。此按钮在界面生成器中具有“等效键”属性,键 ENTER

效果很好,但现在我有一个新的NSComboBox,它应该在用户选择列表项时调用一个方法,或者他按下 Enter / ↵ kbd>.

但是,当我按 Enter 时,主按钮会收到通知并关闭窗口。如何预防?

【问题讨论】:

  • 嘿,我想你已经为此获得了赏金,不是吗?

标签: objective-c macos cocoa interface-builder


【解决方案1】:

这是你得到的正常行为,但你可以通过删除和添加等效键来稍微修改一下。

添加以下 NSComboBox 的代表:

- (void)comboBoxWillPopUp:(NSNotification *)notification;{
    [self.closeButton setKeyEquivalent:@""];
}


- (void)comboBoxWillDismiss:(NSNotification *)notification;{
    [self.closeButton setKeyEquivalent:@"\r"];
}

【讨论】:

  • 我明白了,这可能是一个解决方案,谢谢。我唯一不喜欢的是,我需要为添加到视图中的每个小部件添加这些行……如果我需要在其上使用 Enter 键。
  • 因此您可以选择任何其他键,但在 Mac OS X 应用程序中,您很少有很多键盘快捷键,不是吗?或者您仍然可以要求用户使用tab 进行选择。
  • 我至少有 2 种情况,我确信用户会自发按下 Enter:在组合框中键入新值后,以及编辑 NSTableView 单元格后。基本上,每次他们输入内容时,他们很可能会按 Enter 提交值。
  • 在某些情况下,从提交中删除 Enter。并使其只能点击,并添加 Cmd+Enter 作为快捷方式。然后,您应该为此显示工具提示。
  • 好的,我找到了一个稍有延迟的解决方案。将最后一行更改为 [self.closeButton performSelector:@selector(setKeyEquivalent:) withObject:@"\r" afterDelay:0.01];
【解决方案2】:

防止输入通知的一种解决方法如下:-

//将此操作方法连接到您的组合框,并在其中设置一个BOOL 标志为yes

- (IBAction)comBoxItm:(id)sender
{
    self.isEnterCalled=YES;
}

//现在在调用关闭窗口的某个方法中检查这个标志

-(void)someMethod
{
//Check the flag value if it is yes then just ignore it
if (!self.isEnterCalled)
{
//Close window logic
}
self.isEnterCalled=NO;
}

【讨论】:

    【解决方案3】:

    遇到了同样的问题。有“热键”,我想在编辑一些文本字段时关闭它。我为自己找到了解决方案。无需重写大量 NSTextField 基方法。

    首先,我删除了所有“关键等效项”。我曾经使用NSEvent+ (void)addLocalMonitorForEventsMatchingMask:(NSEventMask)mask handler:(NSEvent *(^)(NSEvent *))block 类方法检测Enter 键。您将块作为参数传递,您可以在其中检查某些条件。第一个参数是事件掩码。你的任务是NSKeyDownMask,在NSEvent Reference Page寻找其他掩码

    参数块将在用户每次按下按钮时执行。您应该检查它是否按下了右键,并且 - 通常 - 当前窗口的第一响应者不是一些可编辑的控件。为此,我们需要 NSWindow 类别类,只是不要在每次处理 NSKeyDownMasked 本地监视器时实现此代码。

    NSWindow+Responders类列表:

    @interface NSWindow (Responders)
    
    - (BOOL)isEditableFirstResponder;
    
    @end
    
    @implementation NSWindow (Responders)
    
    - (BOOL)isEditableFirstResponder
    {
      if (!self.firstResponder)
        return NO; // no first responder at all
      if ([self.firstResponder isKindOfClass:[NSTextField class]]) // NSComboBox is NSTextField subclass
        {
          NSTextField *field=(NSTextField *)self.firstResponder;
          return field.isEditable;
        }
      if ([self.firstResponder isKindOfClass:[NSButton class]]) // yep, buttons may be responders
        return YES;
      return NO; // the first responder is not NSTextField or NSButton subclass - not editable
    }
    
    @end
    

    不知道是否有其他方法可以检查我们现在是否正在编辑某些文本字段或组合框。所以,至少有一部分是你在类的某个地方添加本地监视器(NSWindow、NSView、一些控制器等)。

    - (void)someMethod
    {
      id monitor=[NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:(NSEvent *)^(NSEvent *theEvent){
        if (theEvent.keyCode==/*Enter key code*/ && ![self.window.isEditableFirstResponder]) // you should check the key modifiers too
        {
          // your code here
        }
        return theEvent; // you may return the event to pass the key to the receiver
      }];
    } 
    

    本地监视器是有关 Apple 规则的安全补救措施。它仅在您的应用程序内部有效。对于全局按键事件,您可以使用 addGlobalMonitor,但 Apple 可能会从 AppStore 拒绝您的应用。

    并且不要忘记在不需要时移除显示器。

    - (void)viewControllerShutdownMethod
    {
      [NSEvent removeMonitor:monitor];
    }
    

    祝你好运。

    【讨论】:

      猜你喜欢
      • 2015-12-20
      • 2014-01-13
      • 1970-01-01
      • 2018-04-15
      • 2011-06-14
      • 1970-01-01
      • 1970-01-01
      • 2021-05-21
      相关资源
      最近更新 更多