【问题标题】:how to detect double Click in NSTextField如何检测 NSTextField 中的双击
【发布时间】:2015-12-01 06:00:35
【问题描述】:

我有一个自定义的 NSTextField,我想检测用户在文本字段中的双击。我的目标:我希望能够双击表达式中的括号,例如“(2+2) = 4”,并让它选择匹配括号内的所有内容。以为我可以这样做......

- (void)textView:(NSTextView *)textView doubleClickedOnCell:(id <NSTextAttachmentCell>)cell inRect:(NSRect)cellFrame atIndex:(NSUInteger)charIndex;

但它永远不会在我的自定义 NSTextField 中被调用。

然后我想我可以覆盖 -mouseDown,但这也没有被调用。我难住了。关于什么应该是一个易于实现的功能的任何建议。

谢谢!

菲利普

【问题讨论】:

  • - textView:doubleClickedOnCell:inRect:atIndex: 在您的文本字段的 delegate 上调用,而不是在您的自定义 NSTextView 上。
  • 文本字段处理编辑的文本视图的代表(字段编辑器)。但无论如何,该方法仅适用于附件。
  • 我的文本字段被调用 textView:menu:forEvent:atIndex: 和 textView:shouldChangeTextInRange:replacementString:,但不是 doubleClickedOnCell: 所以 Ken 是正确的,文本字段是文本视图的代表这是处理编辑(字段编辑器)。
  • 也许您可以在作为自定义字段编辑器提供的NSTextView 的子类中覆盖mouseDown:

标签: cocoa nstextfield double-click


【解决方案1】:

文本字段不处理编辑,因此。当文本字段具有焦点时,文本 view 会添加到窗口中,与文本字段的区域重叠。这称为"field editor",它负责处理编辑。

似乎最有可能更改双击行为的地方是该文本视图使用的文本存储对象。 NSTextStorage 继承自 NSMutableAttributedString,后者继承自 NSAttributedString,后者具有 -doubleClickAtIndex: 方法。该方法返回应通过双击特定索引来选择的文本范围。

因此,您需要实现NSTextStorage 的子类,它会覆盖该方法并在某些情况下返回不同的结果。 NSTextStorage 是类簇的半抽象基类。对它进行子类化需要比平时多一点。您必须实现NSAttributedStringNSMutableAttributedString 的原始方法。见the docs about it

有几个地方可以通过将其文本存储对象替换为您的类的实例来自定义字段编辑器:

  • 您可以实现NSTextFieldCell 的自定义子类。将您的文本字段设置为将其用作其单元格。在您的子类中,覆盖-fieldEditorForView:。在您的覆盖中,实例化一个NSTextView。获取它的layoutManager 并在其上调用-replaceTextStorage:,将您的自定义文本存储类的实例传递给它。 (这比将文本编辑所涉及的对象层次结构组合起来更容易,尽管您可以自己完成。)将文本视图的 fieldEditor 属性设置为 true 并返回它。
  • 在您的窗口委托中,实现-windowWillReturnFieldEditor:toObject:。如上所述,使用您的自定义文本存储创建、配置和返回 NSTextView

【讨论】:

    【解决方案2】:

    Ken Thomases 的答案在其对有关字段编辑器以及如何替换它的问题的分析中是正确的,但它随后推荐的解决方案 - 替换字段编辑器的 NSTextStorage - 不是正确的解决方案,据苹果称。在their doc 中,他们特别建议应该使用selectionRangeForProposedRange:granularity: 方法来进行分隔符平衡。根据 Ken 的回答,一旦有了自定义字段编辑器,您就应该使用 NSTextView here 的解决方案,并将其应用于您用于字段编辑器的自定义 NSTextView 子类。

    如果感兴趣,使用NSTextStoragedoubleClickAtIndex: 方法进行分隔符平衡可能是错误的解决方案,原因有几个:(1)因为Apple 这么说,(2)因为子类化NSTextStorage复杂且容易出错,并且 (3) 因为NSTextView 提供了一种专门用于处理分隔符平衡等目的的方法。但是由于一个不重要的原因,它也是错误的:(4) doubleClickAtIndex: 被记录为“返回在给定索引周围形成单词(或其他语言单位)的字符范围,同时考虑到语言特征”。所以doubleClickAtIndex: 实际上是关于如何定义文本(即单词)的语言单位,并且以某种方式重新定义这些以使分隔符平衡工作可能会破坏单词级文本的其他方面加工。例如,我猜想如果您已经覆盖 doubleClickAtIndex: 来进行分隔符平衡,那么要让双击拖动(逐字拖出选择)正常工作会非常棘手。 Cocoa 也可以将doubleClickAtIndex: 用于其他方面的查词,并且将来可能会添加更多的用途。由于分隔符平衡的文本部分不是“单词”,谁知道会导致什么怪异。

    【讨论】:

      【解决方案3】:

      很简单,只需使用这个类来检测双击

      final class doubleClickableTextField : NSTextField {
      
        override func mouseDown(with event: NSEvent) {
          super.mouseDown(with: event)
      
          if (event.clickCount == 2){
            // do the work here
              self.isEditable = true
          }
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-18
        • 2011-01-14
        • 2015-11-09
        • 1970-01-01
        • 2015-06-23
        • 1970-01-01
        • 2011-10-05
        • 1970-01-01
        相关资源
        最近更新 更多