【问题标题】:How to change only font size for the whole styled text in NSTextView如何仅更改 NSTextView 中整个样式文本的字体大小
【发布时间】:2010-02-11 15:05:28
【问题描述】:

我需要为使用多种字体的选定富文本设置文本大小(例如设置为 42)。

我想我可以检查每组字符的属性,修改字体大小并重新设置属性,但是看着浮动的字体面板,似乎应该有一种非常简单直接的方法来实现这一点。我错过了什么明显的东西吗?

【问题讨论】:

    标签: objective-c cocoa macos nstextview


    【解决方案1】:

    在 10.6 上,有一种方便的方法可以迭代属性并增加字体大小。 可以将此方法添加到 NSTextView 类别中。

        - (IBAction)increaseFontSize:(id)sender
    {
        NSTextStorage *textStorage = [self textStorage];
        [textStorage beginEditing];
        [textStorage enumerateAttributesInRange: NSMakeRange(0, [textStorage length])
                                         options: 0
                                      usingBlock: ^(NSDictionary *attributesDictionary,
                                                    NSRange range,
                                                    BOOL *stop)
         {
    #pragma unused(stop)
             NSFont *font = [attributesDictionary objectForKey:NSFontAttributeName];
             if (font) {
                 [textStorage removeAttribute:NSFontAttributeName range:range];
                 font = [[NSFontManager sharedFontManager] convertFont:font toSize:[font pointSize] + 1];
                 [textStorage addAttribute:NSFontAttributeName value:font range:range];
             }
         }];
        [textStorage endEditing];
        [self didChangeText];
    
    }
    

    【讨论】:

      【解决方案2】:

      稍微概括一下乔纳森的回答,这是一个类别界面,您可以简单地将其粘贴到 Xcode 项目中的适当文件中:

      @interface NSTextView (FrameworkAdditions)
      
      -  (IBAction)decrementFontSize:(id)sender;
      -  (IBAction)incrementFontSize:(id)sender;
      
      @end
      

      以及对应的实现:

      @implementation NSTextView (FrameworkAdditions)
      
      - (void)changeFontSize:(CGFloat)delta;
      {
          NSFontManager * fontManager = [NSFontManager sharedFontManager];
          NSTextStorage * textStorage = [self textStorage];
          [textStorage beginEditing];
          [textStorage enumerateAttribute:NSFontAttributeName
                                  inRange:NSMakeRange(0, [textStorage length])
                                  options:0
                               usingBlock:^(id value,
                                            NSRange range,
                                            BOOL * stop)
           {
               NSFont * font = value;
               font = [fontManager convertFont:font
                                        toSize:[font pointSize] + delta];
               if (font != nil) {
                   [textStorage removeAttribute:NSFontAttributeName
                                          range:range];
                   [textStorage addAttribute:NSFontAttributeName
                                       value:font
                                       range:range];
               }
           }];
          [textStorage endEditing];
          [self didChangeText];
      }
      
      -  (IBAction)decrementFontSize:(id)sender;
      {
          [self changeFontSize:-1.0];
      }
      
      -  (IBAction)incrementFontSize:(id)sender;
      {
          [self changeFontSize:1.0];
      }
      
      @end
      

      【讨论】:

        【解决方案3】:

        这将使字体大小加倍,但您可以将 scale 属性更改为任何值,或提供您的固定大小

            NSFont * font = ...;
            CGFloat fontSize =  [[font fontDescriptor].fontAttributes[NSFontSizeAttribute] floatValue];
            font = [NSFont fontWithDescriptor:[font fontDescriptor] size:fontSize * 2.];
        
            self.textField.font = font;
        

        【讨论】:

        • 这对我有用,看起来比其他答案更简单。这是 Swift 3 版本font = NSFont.init(descriptor: font.fontDescriptor, size: ...)
        【解决方案4】:

        注意:我假设您使用的是 NSTextView,并且您可以访问它的文本存储 (NSTextStorage)。

        我认为不可能只更改使用多种字体的文本的字体大小。在 NSAttributedString 中,字体的大小是 NSFontAttributeName 属性的一部分,该属性控制字体和大小。

        一种解决方案是迭代选择并使用@987654321@ 捕获每种字体应用时的范围,更改字体大小,然后使用@987654322@ 在该范围内设置新字体。

        更新

        如果您查看GNUstep GUI source code for NSTextView(在 LGPL 下),您会发现它们的实现使用了范围迭代。

        【讨论】:

        • 是的,这是我首先想到的。但是已经有一种使文本变大或变小的机制。如果某个菜单项或滑块的标签为 3(或 4)并向 NSFontManager 发送 modifyFont: 消息,则 NSFontManager 与 NSTextView 对话并将文本大小更改为较小或较大的值(并保留字体、样式等)。它是自动完成的。所以我想我想加入这个机制,但只是不知道我可以在哪里做。如果有可能的话。
        • 有一个仅在 NSText 实例和 NSFontManager 之间起作用的内置机制(参见developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/…)。基本上,当 FontPanel 更改字体(大小或特征)时,它会向响应者链发送一个 changeFont: 消息。如果找到响应者,它会针对每个文本范围向 FontManager 发送一个 convertFont: 消息。如果你不使用 FontPanel,恐怕你必须复制里面所做的事情......
        • 是的,看起来是这样。我最终使用了 attribute:atIndex:longestEffectiveRange:inRange: 和 convertFont:toSize: 但对我来说很奇怪没有设置字体大小的简单方法(考虑到有增加或减小字体大小的方法,我可以使用,但是我只是不需要它)。谢谢你,劳伦特。
        【解决方案5】:

        由于NSTextViewNSView 的子类,您可以使用-scaleUnitSquareToSize: 更改文本视图的放大级别。例如,要使您调用的所有文本变大:

        [textView scaleUnitSquareToSize:NSMakeSize(2.0, 2.0)];
        

        执行此操作后,您可能需要对文本视图的NSTextContainer 的尺寸进行一些调整,以确保文本布局正确。

        【讨论】:

        • 我只需要真正改变字体大小,而不是缩放视图,但无论如何谢谢,我不知道存在这种方法。
        • @Rob 这太棒了!这正是需要的,而不是我认为需要的(即枚举字体属性以更改它们的相对大小,这可能会惹恼用户并产生其他问题)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-09
        • 1970-01-01
        • 2016-06-07
        • 1970-01-01
        • 2019-12-16
        • 1970-01-01
        • 2022-09-10
        相关资源
        最近更新 更多