附加到NSTextView

时间:2012-04-03 12:12:49

标签: objective-c cocoa scroll append nstextview

我在后台运行了NSTask(设置了NSPipe)我希望在NSTextView中输出内容,因为它们正在进入(output)。

我正在使用的代码是:

NSMutableAttributedString* str = [[NSMutableAttributedString alloc] initWithString:s];
//[str addAttribute:NSForegroundColorAttributeName value:[NSColor whiteColor] range:NSMakeRange(0, [str length])];

[[output textStorage] appendAttributedString:str];

[output scrollRangeToVisible:NSMakeRange([[output string] length], 0)];

问题:

  • 当附加大量数据时,视图似乎“闪烁” ......并且无法正常工作。
  • 鉴于NSTextView位于工作表上,当鼠标指针位于其他位置而不是悬停在NSTextView
  • 上方时,似乎没有显示任何内容
  • 为什么这样,虽然我设置了NSTextView颜色/插入颜色 /等,但这似乎不适用于新插入的文字?
  • 建议的NSTextView附加(+滚动)方式是什么?

谢谢!

2 个答案:

答案 0 :(得分:8)

请记住,用户界面元素(包括NSTextView)在主线程上发挥作用。如果您尝试向文本视图添加信息,那么您最好这样做。方法如下:

[[output textStorage] performSelectorOnMainThread:@selector(appendAttributedString:) 
                                       withObject:str 
                                    waitUntilDone:YES];

我会谈到你的第三点,但坦率地说,这是我仍然非常学生的事情。

为了解决你的第四点,看起来你已经弄清楚了;只需合并你的追加和滚动动作。但就像更改textStorage的内容一样,您希望确保在主线程上执行此操作。由于-scrollRangeToVisible:没有为其参数提供对象,因此您必须以不同的方式执行此操作:

dispatch_async(dispatch_get_main_queue(), ^{
    [output scrollRangeToVisible:NSMakeRange([[output string] length], 0)];
});

尽管我的第一个例子,您也可以将您的电话拨打到-appendAttributedString:内:

dispatch_async(dispatch_get_main_queue(), ^{
    [[output textStorage] appendAttributedString:str];
    [output scrollRangeToVisible:NSMakeRange([[output string] length], 0)];
});

答案 1 :(得分:0)

关于附加到NSTextView的推荐方法:你在appendAttributedString:中表现得很好,但是建议在shouldChangeTextInRange中设置它,然后是beginEditing,appendAttributedString,最后是endEditing:

textStorage = [textView textStorage];
if([textView shouldChangeTextInRange:range replacementString:string])
{
    [textStorage beginEditing];
    [textStorage replaceCharactersInRange:range withAttributedString:attrStr];
    // or if you've already set up the attributes (see below)...
    // [textStorage replaceCharactersInRange:range withString:str];
    [textStorage endEditing];
}

我强烈建议更换scrollRangeToVisible:通过scrollToPoint:,因为scrollRangeToVisible:会导致大量闪烁,当你向下移动“范围”时它也会逐渐变慢。

快速而肮脏的方式可能是这样的:

- (void)scrollToBottom
{
    NSPoint     pt;
    id          scrollView;
    id          clipView;

    pt.x = 0;
    pt.y = 100000000000.0;

    scrollView = [self enclosingScrollView];
    clipView = [scrollView contentView];

    pt = [clipView constrainScrollPoint:pt];
    [clipView scrollToPoint:pt];
    [scrollView reflectScrolledClipView:clipView];
}

我让constrainScrollPoint做所有的计算工作。 我这样做,因为无论如何我的计算失败了(Apple和其他人使用visRect / docRect坐标建议的那些,产生了不可靠的结果)。 reflectScrolledClipView也很重要;它会更新滚动条,使其具有正确的比例和位置。

您可能还会发现滚动发生时很有趣。如果是这样,请同时订阅NSViewBoundsDidChangeNotification和NSViewFrameDidChangeNotification。当其中一个出现时,滚动条位置很可能发生变化(调查[textView visibleRect]和[textView bounds])。

我发现你的文字属性也有问题。我也是这么久了。 我发现附加一个属性字符串会有很多帮助,但对于输入的文本来说仍然不够。 ..然后我发现了关于打字的属性。 在设置NSTextView时,例如在-awakeFromNib中,您可以从以下内容中选择您喜欢的内容......

NSMutableParagraphStyle *paragraphStyle;
float                   characterWidth;
NSFont                  *font;
uint32_t                tabWidth;
NSMutableDictionary     *typingAttributes;

tabWidth = 4;
font = [NSFont fontWithName:@"Monaco" size:9.0];
paragraphStyle = [[textView defaultParagraphStyle] mutableCopy];
if(NULL == paragraphStyle)
{
    paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    // or maybe:
    // paragraphStyle = [NSParagraphStyle new];
}
characterWidth = [[font screenFontWithRenderingMode:NSFontDefaultRenderingMode] advancementForGlyph:(NSGlyph)' '].width;
[paragraphStyle setDefaultTabInterval:(characterWidth * (float) tabWidth];
[paragraphStyle setTabStops:[NSArray array]];
typingAttributes = [[textView typingAttributes] mutableCopy];
if(NULL == typingAttributes)
{
    typingAttributes = [NSMutableDictionary new];
}
[typingAttributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
[typingAttributes setObject:font forKey:NSFontAttributeName];
[textView setTypingAttributes:attributes];

...这比您可能需要的方式更多,但它显示了如何设置字体,标签宽度和输入属性。 NSForegroundColorAttributeName也可能对您有意义(以及一些其他属性,在Xcode中键入NSForegroundColorAttributeName并选项 - 双击它,然后您将看到更多属性(您也可以命令双击;这将带您到头文件中的定义。)