4

我有一个NSTextField根据用户操作设置可编辑的设置。当用户单击窗口内文本字段之外的任何位置时,我想结束编辑。

看起来很简单,但我无法让它工作。我实现了controlTextDidEndEditingand textDidEndEditing,但没有运气,尤其是当我单击不接受第一响应者状态的用户界面元素时。

4

4 回答 4

2

每个 NSEvent 都是通过 NSWindow 的sendEvent:方法传递的。

您可以创建自定义 NSWindow 并覆盖该sendEvent:方法。如果有鼠标按下事件,由 NSNotificationCenter 广播:

- (void)sendEvent:(NSEvent *)event {
    [super sendEvent:event];
    if (event.type == NSLeftMouseDown) {
        [[NSNotificationCenter defaultCenter] postNotificationName:kCustomWindowMouseDown object:self userInfo:@{@"event": event}];
    }
}


在引用 NSTextField 的 ViewController 中,观察此通知:

 [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(customWindowMouseDown:)
                                                 name:kCustomWindowMouseDown
                                               object:self.view.window];


如果鼠标按下事件的位置在文本字段之外,则结束编辑:

- (void)customWindowMouseDown:(id)sender {
    NSNotification *notification = (NSNotification *) sender;

    NSEvent *event = notification.userInfo[@"event"];
    NSPoint locationInWindow = event.locationInWindow;

    if ([self.view.window.firstResponder isKindOfClass:NSTextView.class]) {
        NSTextView *firstResponder = (NSTextView *) self.view.window.firstResponder;

        //we only care about the text field referenced by current ViewController
        if (firstResponder.delegate == (id <NSTextViewDelegate>) self.textField) {

            NSRect rect = [self.textField convertRect:self.textField.bounds toView:nil];

            //end editing if click out side
            if (!NSPointInRect(locationInWindow, rect)) {
                [self.view.window makeFirstResponder:nil];
            }

        }
    }
}
于 2018-12-12T15:16:07.347 回答
0

您可以为 NSView 编写一个子类并编写以下方法并将 nib 文件的 NSWindow 中的 NSView 的类更改为该子类。

 - (void)mouseDown:(NSEvent *)event 
    {
         [text setEditable:NO];
         NSLog(@"mouseDown");
    }
于 2012-10-23T04:57:01.597 回答
0

可能有点脏,但您可以在“文本字段外部”区域创建一个大的透明按钮。编辑开始时显示,编辑结束时隐藏。如果用户点击此按钮,您将停止编辑(并隐藏按钮)。

当我需要一个快速的解决方案时,为我解决了这个问题。

于 2012-10-23T05:17:07.180 回答
0

当您无法对包含视图的窗口进行子类化时,我会改进 vignesh kumar 的答案。

对于所有处理 mouseDown 的子视图/控件,包括超级视图本身,实现:

- (void)mouseDown:(NSEvent *)event
{
    [[self window] makeFirstResponder:self];

    [super mouseDown:event];
}

对于某些控件,例如按钮,您可以更改为

- (void)mouseDown:(NSEvent *)event
{
    [[self window] makeFirstResponder:[self superview]];

    [super mouseDown:event];
}

否则可能会出现对焦环

于 2019-09-12T18:34:56.923 回答