更改 NSTextView 中空格字符的宽度

2024-05-02

我正在尝试制作一个阅读器应用程序来帮助有阅读困难的女孩。一些研究表明,仅仅改变文本、背景和阴影的颜色确实可以帮助孩子们摆脱困境,所以我试图让她这样做。它只是一个带有按钮的大 NSTextView,因此她可以更改字体大小、颜色、背景颜色、阴影属性、字母间距、行间距和字间距。我知道您只需使用 Word 即可完成大部分工作,但我正在努力让她尽可能直观/有趣。

我可以用手的地方是改变单词之间的间距的大小。目前,我只是搜索一串等于我期望的空格数量的空格,然后用更多或更少的空格替换它,如下所示:

- (IBAction)increaseSpacing:(id)sender{ 

  NSInteger spacing = [[NSUserDefaults standardUserDefaults] integerForKey:@"wordSpacing"];
  NSMutableString * oldString = [ NSMutableString stringWithCapacity:0];
  NSMutableString * newString =[ NSMutableString stringWithCapacity:0];

  for (int i = 0; i < spacing; i+=1) {
    [oldString appendString:@" "];
  }

  [newString setString:oldString];
  [newString appendString:@" "];

  [[[textView textStorage] mutableString] replaceOccurrencesOfString:oldString
                           withString:newString options:0
                                range:NSMakeRange(0, [[textView textStorage] length])];

  spacing += 1;

  [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInteger: spacing] forKey:@"wordSpacing"];

}

- (IBAction)reduceSpacing:(id)sender{

  NSInteger spacing = [[NSUserDefaults standardUserDefaults] integerForKey:@"wordSpacing"];

  if (spacing > 1) {

    NSMutableString * oldString = [ NSMutableString stringWithCapacity:0];
    NSMutableString * newString =[ NSMutableString stringWithCapacity:0];

    for (int i = 0; i < spacing-1; i+=1) {

      [newString appendString:@" "];

    }

    [oldString setString:newString];
    [oldString appendString:@" "];

    [[[textView textStorage] mutableString] replaceOccurrencesOfString:oldString
                                                        withString:newString options:0
                                                             range:NSMakeRange(0, [[textView textStorage] length])];
    spacing -= 1;
    [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInteger: spacing] forKey:@"wordSpacing"];

  }

}

这种方法对我来说感觉很草率,尤其是在用箭头键移动光标时。我可以在键入空格字符时更改其字体大小,但这也会更改行高。有没有办法可以改变空格字符的宽度?在此先感谢您的帮助。


我最终的解决方案是将空间替换为具有调整宽度的空白图像(空白)。

基本组成:
a) 用空格代替空格的方法
b) 用空格代替空格的方法
c) NSValueTransformer 为 NSTextView 做 (a) 为transformedValue 和 (b) 为reverseTransformedValue
d) NSTextViewDelegate 在文本更改时执行 (a) 操作
e) 子类 NSTextView 在发送到粘贴板之前对复制或剪切的文本执行 (b) 操作
f) 分配给步进器以更改尺寸的操作

每个部分的代码如下:

a) AppDelegate方法用空格替换空格

- (NSAttributedString * ) replaceSpacesWithBlanks:(NSString *)replaceString {

  CGFloat imageWidth = [[NSUserDefaults standardUserDefaults] integerForKey:@"wordSpacing"];
  NSImage * pic = [[NSImage alloc] initWithSize:NSMakeSize(imageWidth, 1.0f)];

  NSTextAttachmentCell *attachmentCell = [[NSTextAttachmentCell alloc] initImageCell:pic];
  NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
  [attachment setAttachmentCell: attachmentCell ];
  NSAttributedString *replacementString = [NSAttributedString  attributedStringWithAttachment: attachment];

  NSMutableAttributedString *mutableString = [[NSMutableAttributedString alloc] initWithString:replaceString];

  NSRange range = [[mutableString string] rangeOfString:@" "];

  while (range.location != NSNotFound) {

    [mutableString replaceCharactersInRange:range withAttributedString:replacementString];
    range = [[mutableString string] rangeOfString:@" "];

  }

 return [[NSAttributedString alloc] initWithAttributedString: mutableString];

}

b) AppDelegate方法用空格替换空格

- (NSString * ) replaceBlanksWithSpaces:(NSAttributedString *)replaceAttributedString {

  NSMutableAttributedString * mutAttrString = [[NSMutableAttributedString alloc] initWithAttributedString:replaceAttributedString];

  for (int index = 0; index < mutAttrString.length; index += 1) {

    NSRange theRange;
    NSDictionary * theAttributes = [mutAttrString attributesAtIndex:index effectiveRange:&theRange];
    NSTextAttachment *theAttachment = [theAttributes objectForKey:NSAttachmentAttributeName];

    if(theAttachment != NULL) {

      [mutAttrString replaceCharactersInRange:theRange withString:@" "];

    }

  }

  return mutAttrString.string;

}

c) NSValueTransformer,用于 NSTextView 将transformedValue 的空格替换为空格,并将reverseTransformedValue 的空格替换为空格

@implementation DBAttributedStringTransformer

- (id)init
{
  self = [super init];
  if (self) {
    appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
  }
  return self;
}

+ (Class)transformedValueClass
{
  return [NSAttributedString class];
}

+ (BOOL)allowsReverseTransformation
{
  return YES;
}

- (id)transformedValue:(id)value
{
  return [appDelegate replaceSpacesWithBlanks:value];
}

- (id)reverseTransformedValue:(id)value
{
  return [appDelegate replaceBlanksWithSpaces:value];
}

d) NSTextViewDelegate 在文本更改时用空白替换空格

@implementation DBTextViewDelegate

-(void)awakeFromNib {
  appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
}

- (void)textViewDidChangeSelection:(NSNotification *)aNotification{

  // Need to keep track of where the cursor should be reinserted

  textLength = myTextView.string.length;
  insertionPoint = [[[myTextView selectedRanges] objectAtIndex:0] rangeValue].location;

}


//replaces spaces with blank image and puts cursor back in correct position
- (void)textDidChange:(NSNotification *)aNotification{

  NSInteger newTextLength = myTextView.string.length;
  NSInteger newInsertionPoint = insertionPoint + newTextLength - textLength;

  NSString * stringValue = [[NSUserDefaults standardUserDefaults] stringForKey:@"textViewString"];

  NSAttributedString * attrStringWithBlanks = [[ NSAttributedString alloc] initWithAttributedString:[appDelegate replaceSpacesWithBlanks:stringValue ]];

  NSMutableAttributedString *mutableString = [[NSMutableAttributedString alloc] initWithAttributedString:attrStringWithBlanks];

  [myTextView.textStorage setAttributedString: mutableString];

  //Put the cursor back where it was
  [myTextView setSelectedRange:NSMakeRange(newInsertionPoint, 0)];

}

e) 子类 NSTextView 在写入粘贴板之前用复制或剪切文本上的空格替换空白

@implementation DBTextView

-(void)awakeFromNib {

  appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];

}

-(void) selectedTextToClipBoard{

  NSRange selectedRange = [self selectedRange];

  NSAttributedString * selectedText = [[self textStorage] attributedSubstringFromRange: selectedRange];

  NSString * textWithoutBlanks = [appDelegate replaceBlanksWithSpaces:selectedText];

  NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
  [pasteboard clearContents];
  NSArray *copiedObject = [NSArray arrayWithObject:textWithoutBlanks];
  [pasteboard writeObjects:copiedObject];

}

-(void) copy:(id)sender{

  [self selectedTextToClipBoard];

}

-(void) cut:(id)sender{

  [self selectedTextToClipBoard];

  // Delete selected text so it acts like a cut
  NSRange selectedRange = [self selectedRange];
  [[self textStorage] deleteCharactersInRange:selectedRange];

}

f) 分配给步进器以更改尺寸的操作

- (IBAction)changeWordSpacing:(id)sender {

  CGFloat imageWidth = [[NSUserDefaults standardUserDefaults] integerForKey:@"wordSpacing"];
  NSImage * pic = [[NSImage alloc] initWithSize:NSMakeSize(imageWidth, 1.0f)];
  NSTextAttachmentCell *attachmentCell = [[NSTextAttachmentCell alloc] initImageCell:pic];

  NSMutableAttributedString * mutAttrString = [[NSMutableAttributedString alloc] initWithAttributedString:[textView textStorage]];

  for (int index = 0; index < mutAttrString.length; index += 1) {

    NSRange theRange;
    NSDictionary * theAttributes = [mutAttrString attributesAtIndex:index effectiveRange:&theRange];
    NSTextAttachment *theAttachment = [theAttributes objectForKey:NSAttachmentAttributeName];

    if(theAttachment != NULL) {

      [theAttachment setAttachmentCell: attachmentCell ];

    }

  }

  [[textView textStorage] setAttributedString:mutAttrString];

}

另外,NSTextView 应设置为“连续更新值”

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

更改 NSTextView 中空格字符的宽度 的相关文章

  • 在 Objective C 中使用下划线作为属性名称前缀 [重复]

    这个问题在这里已经有答案了 我以前避免在变量名中使用下划线 这可能是我大学 Java 时代的遗留下来的 因此 当我在 Objective C 中定义属性时 我自然会这样做 In the header interface Whatever N
  • 自动布局:Y 位置为两个值中的最大值

    我有一个按钮 play Button 和两个 UIView myView 1 和 myView 2 它们的位置在执行过程中可能会发生变化 我希望 playButton 的顶部比 UIView 1 的底部或 UIView 2 的底部低 10
  • 跟踪所有 ObjC 方法调用?

    有时 当查看别人的大型 Objective C 程序时 很难知道从哪里开始 在这种情况下 我认为记录对每个非 Apple 方法的每次调用会很有帮助 有没有办法做到这一点 基本上 在某个中心位置进行一项更改 并记录调用的每个方法 最好仅限于非
  • Objective-C 实例变量?

    我确信我在这里的困惑只是因为陷入 Java 思维方式 并且不理解 Obj C 在这种情况下有何不同 在Java中 我可以在类中声明一个变量 就像这样 并且每个instance该类的 将会有它自己的 MyClass String myVar
  • iOS:弃用 AudioSessionInitialize 和 AudioSessionSetProperty

    我对 Objective C 很陌生 正在尝试更新一些大约 3 年前的代码以与 iOS 7 一起使用 有两两个实例AudioSessionSetProperty and AudioSessionInitialize出现在代码中 1 void
  • 尝试在 Mac Snow Leopard 上安装 PyCurl 时出现问题

    我的应用程序需要使用 PyCurl 因此我尝试将其安装在我的 Mac 上 但发现了很多问题和错误 要求 首先我必须说我的Mac上运行的Python版本是基于32位的 因为我需要使用WxPython 这需要32位Python 为此 我使用了
  • iOS:从非图像数据生成图像(Godus,如风景)

    所以看到图像后Godus http www kickstarter com projects 22cans project godus我想知道如何生成简单的 非交互式的 2D 图像 with 不同高度或层数的颜色不同就像下面的图片一样 我只
  • 如何将 Spotlight for Help 插入本地化的 macOS 应用程序?

    我正在 macOS 上使用 Swing GUI 框架实现 Java 应用程序 当使用system外观和感觉以及screen菜单栏 Swing 自动插入一个搜索栏 called 聚光灯寻求帮助 https developer apple co
  • 为什么我在 Mac 上看到“java.lang.reflect.InaccessibleObjectException: Unable to make private java.nio.DirectByteBuffer(long,int)accessibl

    我已经在工作中愉快地构建代码好几天了 但突然我的一个项目 不是全部 失败并出现此错误消息 看看下面的答案吧 我是如何修复它的 起初我用谷歌搜索 看到很多有这个问题的人正在使用 Java 16 但我认为 错误 我正在使用 Java 11 因为
  • LaunchAgent 不运行 shell 脚本

    在 Catalina 之前的 macOS 下 我有一个每天运行 shell 脚本的 LaunchAgent 升级并切换到 zsh 后 它不起作用 我检查过的事情 shebang 切换到 zsh shell脚本可以从命令行手动执行 sh 在系
  • Objective-c中的贝塞尔曲线算法

    比我聪明的人可以看一下这个吗 我正在尝试实现我发现的贝塞尔曲线算法here http webtweakers com swag GRAPHICS 0074 PAS html在 Objective c 中 输出是错误的 我想我正确地转换了代码
  • 阻止 OSX 变音符号为所有用户禁用 Java 中的 KeyBindings?

    注 我知道这个问题 https stackoverflow com questions 40335285 java keybinds stop working after holding down a key用户必须输入终端命令才能解决此问
  • 获取 Cocoa 中文件的类型

    我成功找到了指定文件的扩展文件类型 JPEG 图像 TIFF 图像等 但我正在寻找更通用的东西 可以对 大类别 中的文件进行分类 如图像 moovies 文本文件等 有没有办法在可可 或 Objective C 中实现这一点 感谢您的帮助
  • 将第 3 方库添加到 iPhone 应用程序时如何设置“标题搜索路径”的路径

    我想添加第 3 方库语音转文本 https github com todoroo iPhone Speech To Textto my Xcode项目 我只是拖xcodeproj文件在我的 iPhone 项目中 然后我按照目标依赖项 将二进
  • python 找不到 pydicom 模块

    错误信息 In 1 import pydicom as dicomio ImportError Traceback most recent call last
  • 防止 UITableView 滚动到某个点以下

    如何让 UITableView 允许在某个索引行上方滚动 但在低于某个点时阻止滚动 例如 如果我有第 1 行到第 100 行 其中在给定时间视图中仅出现 5 行 我希望允许用户在第 1 50 行之间滚动 但在第 50 行可见时阻止进一步向下
  • 在 macOS 10.14 上键入文本时,NSTextView 光标不出现

    我在 macOS 10 12 Mojave 上使用 NSTextView 观察到一个奇怪的问题 我正在更改 textStorage 属性didChangeText 像这样 self textStorage beginEditing ARTo
  • 如何确定 UINavigationController 中工具栏的高度?

    我有一个带有由 UINavigationController 呈现的工具栏的视图 当我处理 UIKeyboardWillShowNotification 时 我将整个屏幕向上滚动键盘的高度 问题是当显示键盘时 底部工具栏不显示 所以我只需将
  • 后台模式下的 AVSpeechSynthesizer

    我无法获取 iOS 7AVSpeechSynthesizer当我的 iOS 应用程序处于后台模式时工作 我添加了 应用程序播放音频 应用程序支持的后台模式的关键 但我仍然无法让它工作 我还研究了创建一个AVMutableCompositio
  • iOS SDK:MapKit MKPolyLine 未显示

    我试图在地图上显示多段线 但该线没有显示 我尝试了很多事情 但注意到似乎有用 我检查了核心数据函数 它正在返回数据 所以这不是问题 它必须是我在地图点创建或地图上绘制的某个地方 我猜 我确信一定是某个地方出了点小错误 但我找不到它 My c

随机推荐

  • C#中同步接口和实现注释的方法

    是否有自动方法在接口及其实现之间同步注释 我目前正在记录它们 并且不想手动使它们保持同步 UPDATE 考虑这段代码 interface IFoo
  • Spring Web 连接到嵌入 Jboss 服务器 7.1.1 的 HornetQ JMS

    我正在尝试设置 spring web 以通过以下方式连接到远程 Jboss 7 1 1 HornetQ JMSthis http java dzone com articles connecting spring地点 但我收到以下错误 是否
  • 检索属于特定命名空间的所有实体时返回的内部类型

    我正在尝试检索属于特定名称空间的所有实体 查询非常简单 query datastore Query namespace
  • 如何阻止连续打印多个买入/卖出信号?

    我正在尝试用我的脚本实现一些目标 如果前一个信号是 卖出 我只想打印 买入 信号 反之亦然 我只想在小于之前的 卖出 信号时打印 买入 信号 反之亦然 我一整天都在努力寻找这个问题的解决方案 我不明白如何使用 valuewhen 或 bar
  • 如何通过管道将输入和输出传送到交互式 shell?

    我正在尝试构建一个应用程序 使用户能够与命令行交互式 shell 例如 IRB 或 Python 进行交互 这意味着我需要将用户输入通过管道传输到 shell 并将 shell 的输出返回给用户 我希望这会像管道 STDIN STDOUT
  • Android 数据库(SQLite)从空表返回非空游标

    我使用 SQLite 数据库浏览器验证该表不包含任何行 我单步执行查询生成器代码来获取生成的查询 并在 SQLite 数据库浏览器中运行该查询 查询返回零行 但是 Android 的 SQLiteQueryBuilder query 方法返
  • 如何了解来自不同...“命名空间”的变量?

    如何从外部 javascript 文件中访问在另一个地方声明的某个变量 假设在一个 html 文件中我有以下内容 在 otherfile html 的部分中 我有 alert a 我如何确保收到一条提示消息 某事 我认为Google Ads
  • 使用 webpacker 部署到 heroku 后,资产不存在于资产管道中

    我正在使用 Rails 5 2 3 我可以在本地下载 pdf 但Heroku它通过错误 500 错误是 ActionView Template Error 资源 pdf css 不存在于资源管道中 这是我的 Heroku 日志 2019 0
  • 如何在android上的manageQuery中添加限制子句

    Android 的 API 通过 SQLite 提供了一种干净的机制来查询联系人列表 但是 我不确定如何限制结果 Cursor cur Activity mCtx managedQuery People CONTENT URI column
  • 如何清除gwt中的缓存?

    我怎样才能清除缓存gwt 或者有什么方法可以阻止浏览器保留缓存gwt 当您部署 GWT 应用程序时 避免代理和浏览器缓存 GWT 生成的 nocache js 文件非常重要 一种解决方案是实现一个 Servlet 过滤器 添加控制缓存行为的
  • 如何在react-native应用程序中禁用屏幕截图?

    我已经使用react native制作了一个移动应用程序 目前只有android 它不是博览会应用程序 我想禁止用户在应用程序打开时截取屏幕截图 我知道不可能完全禁用此功能 但我想让至少更难截取屏幕截图 我找到了一些例子 但我不知道如何实现
  • 一元运算符 ++ 不能应用于 Int 类型的操作数

    为什么下面的 swift 代码会给我带来错误 一元运算符 不能应用于 Int 类型的操作数 在 Xcode 6 3 2 上使用 swift 1 2 struct Set var player1Games Int var player2Gam
  • 如何将多个域路由到多个节点应用程序?

    我习惯了典型的 Lamp Web 托管环境 您只需单击 cpanel 中的几个按钮 您的域就会被分区并映射到 htdocs 中的文件夹 我经常使用 Node js 但做同样的事情似乎并不那么简单 如果我有多个节点应用程序 并且我想将doma
  • 在大型文本文件中查找重复记录

    我在一台 Linux 机器 Redhat 上 并且有一个 11GB 的文本文件 文本文件中的每一行包含单个记录的数据 并且该行的前 n 个字符包含该记录的唯一标识符 该文件包含略多于 2700 万条记录 我需要验证文件中不存在具有相同唯一标
  • 将列从日期转换为日期时间

    我有一个名为Lastmodified 数据类型为Date 但本来应该是DateTime 有没有办法转换列 当我使用 SQL Server Management Studio 的 设计 功能时 出现以下错误 不允许保存更改 您所做的更改需要以
  • C 中的 NULL 是否需要/定义为零?

    在我的 GCC 测试程序中 NULL 似乎为零 但维基百科说NULL只需要指向不可寻址的内存 有编译器做吗NULL非零 我很好奇是否if ptr NULL 是比更好的练习if ptr NULL is guaranteed to be zer
  • 如何禁用 AngularJS 中输入的修剪?

    我发现了一些奇怪的行为 默认情况下角度修剪模型值 快速谷歌搜索并不能帮助我解决这个问题 我发现了ng no trim指导性建议 ng trim等等 但没有任何作用 我在下面提供了一个代表这个问题的小片段 function Ctrl scop
  • 解压缩 GZIP http 响应(使用 jersey 客户端 api、java)

    有人可以告诉我在从某些 Http 调用获取响应时需要做什么才能解压缩 GZIP 内容吗 为了进行调用 我使用 Jersey Client API 请参阅下面的代码 String baseURI http api stackoverflow
  • 在 C++ 中是否有一种简单的方法可以将由空格字符分隔的一行输入拆分为整数?

    我是一名 C 初学者 我一直在开发一个项目 在该项目中 您必须输入一些用空格分隔的整数 并且程序必须输出所有可能的整数排列 我知道在 python 中 这可以使用 int item for item in input split 但我不知道
  • 更改 NSTextView 中空格字符的宽度

    我正在尝试制作一个阅读器应用程序来帮助有阅读困难的女孩 一些研究表明 仅仅改变文本 背景和阴影的颜色确实可以帮助孩子们摆脱困境 所以我试图让她这样做 它只是一个带有按钮的大 NSTextView 因此她可以更改字体大小 颜色 背景颜色 阴影