簡體   English   中英

NSTextField:當用戶在文本字段之外單擊時結束編輯

[英]NSTextField: end editing when user clicks outside of the text field

我有一個NSTextField ,我可以根據用戶操作將其設置為可編輯。 當用戶單擊窗口內文本字段之外的任何位置時,我想結束編輯。

看起來很簡單,但是我無法使它正常工作。 我實現了controlTextDidEndEditingtextDidEndEditing ,但是沒有運氣,特別是當我單擊不接受第一響應者狀態的用戶界面元素時。

您可以為NSView編寫一個子類,並編寫以下方法,然后將nib文件的NSWindow中的NSView的類更改為該子類。

 - (void)mouseDown:(NSEvent *)event 
    {
         [text setEditable:NO];
         NSLog(@"mouseDown");
    }

可能有點臟,但是您可以在“文本字段的外部”區域中創建一個大的透明按鈕。 編輯開始時顯示它,編輯結束時隱藏它。 如果用戶點擊此按鈕,則停止編輯(並隱藏該按鈕)。

當我需要快速解決方案時,為我解決了這個問題。

每個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];
            }

        }
    }
}

當您無法對包含視圖的窗口進行子類化時,我會改善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];
}

否則可能會出現聚焦環

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM