在焦点上选择NSTextField的文本

时间:2010-02-03 21:45:28

标签: cocoa select focus nstextfield

当用户点击NSTextField时,有人会建议选择NSTextField的所有文字吗?

我确实找到了对mouseDown进行子类化的建议,然后使用firstResponder或{{1}},但现在已超出我的技能范围了。所以我希望有一个更简单的解决方案,或者有人可能会详细说明所需的步骤。

4 个答案:

答案 0 :(得分:23)

没有更简单的解决方案,您需要将NSTextField子类化为您想要的。如果要在Cocoa中执行任何有用的操作,您将需要学习如何处理子类。

文本字段对于子类来说可能相对复杂,因为NSTextField使用称为“字段编辑器”的单独NSTextView对象来处理实际编辑。此文本视图由NSWindow的{​​{1}}对象返回,并重新用于页面上的所有文本字段。

与任何NSTextField子类一样,NSResponder会对方法NSTextField-acceptsFirstResponder做出响应。当窗口想要将焦点放在特定控件或视图上时,会调用它们。如果从这两种方法返回-becomeFirstResponder,那么您的控件/视图将具有第一响应者状态,这意味着它是活动控件。但是,如上所述,NSTextField实际上在单击时为字段编辑器提供了第一个响应者状态,因此您需要在YES子类中执行类似的操作:

NSTextField

这首先调用超类的@implementation MCTextField - (BOOL)becomeFirstResponder { BOOL result = [super becomeFirstResponder]; if(result) [self performSelector:@selector(selectText:) withObject:self afterDelay:0]; return result; } @end 实现,它将完成管理字段编辑器的艰苦工作。然后调用-becomeFirstResponder选择字段中的所有文本,但是在延迟0秒之后它会这样做,这将延迟到下一次运行事件循环。这意味着在完全配置字段编辑器后将进行选择。

答案 1 :(得分:5)

@Rob的答案可能在某一点上起作用,但正如@Daniel指出的那样,它不再起作用了。看起来Cocoa想要跟踪鼠标并拖出一个选择以响应点击,并且尝试选择响应becomeFirstResponder的文本并不能很好地发挥作用。

需要拦截鼠标事件,以防止跟踪。或多或少通过反复试验,我找到了一个似乎适用于OS X 10.10的解决方案:

@interface MyAutoselectTextField : NSTextField
@end

@implementation MyAutoselectTextField
- (void)mouseDown:(NSEvent *)theEvent
{
    [[self currentEditor] selectAll:nil];
}
@end

据我所知,当mouseDown:被调用时,字段编辑器已经设置好,可能是becomeFirstResponder的副作用。调用selectAll:然后选择字段编辑器的内容。在selectText:上调用self代替效果不佳,可能是因为设置了字段编辑器。请注意,此处覆盖mouseDown: 调用super; super会运行跟踪循环,拖出选择,我们不想要这种行为。请注意,一旦文本字段成为第一响应者,此mouseDown:覆盖不会影响选择,因为此时正在调用字段编辑器mouseDown:

我不知道这个OS X版本的范围是多少;如果你关心,你需要测试它。不幸的是,使用NSTextField总是有点脆弱,因为字段编辑器的工作方式非常奇怪,因此依赖于super中的实现细节。

答案 2 :(得分:2)

Swift的一些更新:

import Cocoa

class TextFieldSubclass: NSTextField {
    override func mouseDown(theEvent: NSEvent) {
        super.mouseDown(theEvent)
        if let textEditor = currentEditor() {
            textEditor.selectedRange = NSMakeRange(location, length)
        }
    }
}

或者是为了精确选择:

import Cocoa

class TextFieldSubclass: NSTextField {
    override func becomeFirstResponder() -> Bool {
        let source = CGEventSourceCreate(CGEventSourceStateID.HIDSystemState)
        let tapLocation = CGEventTapLocation.CGHIDEventTap
        let cmdA = CGEventCreateKeyboardEvent(source, 0x00, true)
        CGEventSetFlags(cmdA, CGEventFlags.MaskCommand)
        CGEventPost(tapLocation, cmdA)
        return true
    }
}

Swift版本,适用于我:

{{1}}

答案 3 :(得分:0)

我知道这是一个古老的问题,但这是为那些可能迷失于此的人提供的更新。

重写NSTextField并连接到beginFirstResponder()中。您不必担心管理代表或点击。棘手的部分是首先要为重点文本字段找到字段编辑器,然后再要求它选择所有文本。

Objective-C

// in AutoselectOnFocusTextField.h
@interface AutoselectOnFocusTextField : NSTextField
@end

// in AutoselectOnFocusTextField.m
@implementation AutoselectOnFocusTextField
- (BOOL)becomeFirstResponder {
    if (![super becomeFirstResponder]) {
        return NO;
    }
    NSText* fieldEditor = [self currentEditor];
    if (fieldEditor != nil) {
        [fieldEditor performSelector:@selector(selectAll:) withObject:self afterDelay:0.0];
    }
    return YES;
}
@end

快速

class AutoselectOnFocusTextField: NSTextField {
    override func becomeFirstResponder() -> Bool {
        guard super.becomeFirstResponder() else {
            return false
        }
        if let editor = self.currentEditor() {
            editor.perform(#selector(selectAll(_:)), with: self, afterDelay: 0)
        }
        return true
    }
}