我有自定义的NSTextField,我想在文本字段中检测用户的双击。我的目标:我希望能够双击表达式中的括号,例如"(2 + 2)= 4"并让它选择匹配括号内的所有内容。以为我可以用......来做到这一点。
- (void)textView:(NSTextView *)textView doubleClickedOnCell:(id <NSTextAttachmentCell>)cell inRect:(NSRect)cellFrame atIndex:(NSUInteger)charIndex;
但它永远不会在我的自定义NSTextField中调用。
然后我想我可以覆盖-mouseDown,但是也没有被调用。我很难过。对于什么应该是一个容易实现的功能的任何建议。
谢谢!
菲利普
答案 0 :(得分:2)
很简单,只需使用此类来检测双击
final class doubleClickableTextField : NSTextField{
override func mouseDown(with event: NSEvent) {
if (event.clickCount == 2){
// do the work here
self.isEditable = true
}
}
}
答案 1 :(得分:1)
文本字段不处理编辑。当文本字段具有焦点时,文本视图将添加到窗口,与文本字段的区域重叠。这称为"field editor",它负责处理编辑。
您最有可能更改双击行为的地方是该文本视图使用的文本存储对象。 NSTextStorage
继承自NSMutableAttributedString
继承自NSAttributedString
的{{1}}方法。该方法返回应通过双击特定索引来选择的文本范围。
因此,您希望实现一个-doubleClickAtIndex:
的子类来覆盖该方法,并在某些情况下返回不同的结果。 NSTextStorage
是类集群的半抽象基类。对它进行子类化需要比平时多一点。您必须实现NSTextStorage
和NSAttributedString
的原始方法。请参阅the docs about it。
有一些地方可以自定义字段编辑器,方法是将文本存储对象替换为类的实例:
NSMutableAttributedString
的自定义子类。设置文本字段以将其用作其单元格。在您的子类中,覆盖NSTextFieldCell
。在您的覆盖中,实例化-fieldEditorForView:
。获取其NSTextView
并在其上调用layoutManager
,并将其传递给自定义文本存储类的实例。 (这比将文本编辑所涉及的对象的层次结构放在一起更容易,尽管您可以自己执行此操作。)将文本视图的-replaceTextStorage:
属性设置为true并将其返回。fieldEditor
。如上所述,使用自定义文本存储创建,配置和返回-windowWillReturnFieldEditor:toObject:
。 答案 2 :(得分:0)
Ken Thomases在这里回答关于字段编辑器的问题以及如何替换它的问题是正确的,但它建议的解决方案 - 替换字段编辑器的NSTextStorage
是不正确的解决方案,据苹果公司称。在their doc中,他们特别建议对于分隔符平衡,应使用selectionRangeForProposedRange:granularity:
方法。根据Ken的回答,一旦你有一个自定义字段编辑器,你应该使用NSTextView
here的解决方案,应用于你用于字段编辑器的自定义NSTextView
子类。
如果感兴趣的话,使用NSTextStorage
的{{1}}方法进行分隔符平衡可能是错误的解决方案,原因有几个:(1)因为Apple这样说,(2)因为子类化doubleClickAtIndex:
是复杂且容易出错的,并且(3)因为NSTextStorage
提供了一种专门用于执行分隔符平衡等操作的方法。但是出于一个非平凡的原因也是错误的:(4)NSTextView
被记录为“返回围绕给定索引形成单词(或其他语言单位)的字符范围,将语言特征考虑在内”。所以doubleClickAtIndex:
实际上是关于如何定义文本的语言单位(即单词),并以某种方式重新定义这些单元以进行分隔符平衡工作可能会破坏单词的其他方面 - 级文本处理。例如,我猜想如果你已经覆盖doubleClickAtIndex:
来进行分隔符平衡,那么双击拖动(逐字拖出选择)工作正常是非常棘手的。 Cocoa也可以使用doubleClickAtIndex:
来进行单词查找的其他方面,并可能在将来添加更多用途。由于文本的分隔符平衡部分不是“单词”,谁知道可能会产生什么奇怪之处。