Присоединение к NSTextView - PullRequest
2 голосов
/ 03 апреля 2012

У меня 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
  • Почему, хотя я установил цвет / цвет вставки / etc для NSTextView, это не относится к вновь вставленному тексту?
  • Что такое рекомендуемый способ добавления (+ прокрутка) на NSTextView?

Спасибо!

Ответы [ 2 ]

8 голосов
/ 04 апреля 2012

Помните, что элементы пользовательского интерфейса, включая 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)];
});
0 голосов
/ 16 февраля 2013

Относительно рекомендованного способа добавления к 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];
}

Я позволил restinScrollPoint выполнить всю работу по вычислению.Я делаю это, потому что мои вычисления все равно не сработали (те, которые были предложены Apple и другими, которые использовали координаты visRect / docRect, дали ненадежные результаты).отражениеScrolledClipView также важно;он обновляет полосу прокрутки, чтобы иметь правильную пропорцию и положение.

Вам также может быть интересно узнать, когда произошла прокрутка.Если это так, подпишитесь как на 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 также может быть интересным для вас (как и некоторые другие атрибуты, введите NSForegroundColorAttributeName в Xcode и дважды щелкните по нему опцию, затем вы увидите еще несколько атрибутов (вы также можете дважды щелкнуть по команде; для этого потребуетсяк определению в заголовочном файле).

...