objective-c - 使用 NSTextView 伪造 NSTextField 以获得漂亮的颜色?

标签 objective-c cocoa macos nstextfield nstextview

尝试更改 NSTextField 的选定文本背景颜色(我们有一个深色 UI,并且选定的文本背景几乎与文本本身相同),但似乎只有 NSTextView 允许我们更改此设置。

因此,我们尝试使用 NSTextView 伪造 NSTextField,但无法让文本滚动以同样的方式工作。

我们得到的最接近的是这段代码:

NSTextView *tf = [ [ NSTextView alloc ] initWithFrame: NSMakeRect( 30.0, 20.0, 80.0, 22.0 ) ];

// Dark UI
[tf setTextColor:[NSColor whiteColor]];
[tf setBackgroundColor:[NSColor darkGrayColor]];

// Fixed size
[tf setVerticallyResizable:FALSE];
[tf setHorizontallyResizable:FALSE];

[tf setAlignment:NSRightTextAlignment]; // Make it right-aligned (yup, we need this too)

[[tf textContainer] setContainerSize:NSMakeSize(2000, 20)]; // Try to Avoid line wrapping with this ugly hack
[tf setFieldEditor:TRUE]; // Make Return key accept the textfield

// Set text properties
NSMutableDictionary *dict = [[[tf selectedTextAttributes] mutableCopy ] autorelease];
[dict setObject:[NSColor orangeColor] forKey:NSBackgroundColorAttributeName];
[tf setSelectedTextAttributes:dict];

几乎可以正常工作,只是如果文本比文本字段长,则您无法以任何方式滚动到它。

知道如何实现这一目标吗?

提前致谢

编辑: Joshua Nozzi 下面建议的解决方案

感谢 Joshua,这是我一直在寻找的一个很好的解决方案:

@interface ColoredTextField : NSTextField
- (BOOL)becomeFirstResponder;
@end

@implementation ColoredTextField
- (BOOL)becomeFirstResponder
{
    if (![super becomeFirstResponder])
        return NO;

    NSDictionary * attributes = [NSDictionary dictionaryWithObjectsAndKeys : 
                     [NSColor orangeColor], NSBackgroundColorAttributeName, nil];

    NSTextView * fieldEditor = (NSTextView *)[[self window] fieldEditor:YES forObject:self];
    [fieldEditor setSelectedTextAttributes:attributes];
    return YES;
}
@end

它不是用 NSTextView 来伪造它,而是一个 NSTextField,当它成为第一响应者时会更改所选文本的颜色。

编辑:一旦您在文本字段中按 Enter 键,上面的代码就会恢复为默认选择颜色。这是避免这种情况的方法。

@interface ColoredTextField : NSTextField
- (BOOL)becomeFirstResponder;
- (void)textDidEndEditing:(NSNotification *)notification;

- (void)setSelectedColor;
@end

@implementation ColoredTextField
- (BOOL)becomeFirstResponder
{
    if (![super becomeFirstResponder])
        return NO;
    [self setSelectedColor];
    return YES;
}

- (void)textDidEndEditing:(NSNotification *)notification
{
    [super textDidEndEditing:notification];
    [self setSelectedColor];
}

- (void) setSelectedColor
{
    NSDictionary * attributes = [NSDictionary dictionaryWithObjectsAndKeys : 
                                [NSColor orangeColor], NSBackgroundColorAttributeName, nil];

    NSTextView * fieldEditor = (NSTextView *)[[self window] fieldEditor:YES forObject:self];
    [fieldEditor setSelectedTextAttributes:attributes];
}
@end

最佳答案

为什么不直接设置文本字段的属性 field editor直接当场becomes first responder

在典型的文本字段中,只有当该字段是第一响应者时,选择才可见,因此,如果您请求文本字段的字段编辑器,然后设置选定的文本属性,您将获得同样的影响,不是吗?

NSDictionary * attributes = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSColor orangeColor], NSBackgroundColorAttributeName, nil];
NSTextView * fieldEditor = (NSTextView *)[[self window] fieldEditor:YES 
    forObject:textField];
[fieldEditor setSelectedTextAttributes:attributes];

注意: 正如下面的评论中所讨论的,文档正确地指出字段编辑器是 NSTextView 的实例,但 -[NSWindow fieldEditor:forObject:] 方法声称返回 NSText (NSTextView 的直接父类(super class))。如果您打算向字段编辑器发送仅限 NSTextView 的方法,则需要将其转换为 NSTextView 以消除编译器的警告。如果将来更正方法原型(prototype),转换不会破坏代码中的任何内容,因此可以安全地将其保留在原处。

关于objective-c - 使用 NSTextView 伪造 NSTextField 以获得漂亮的颜色?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48106765/

相关文章:

ios - 根据 NSDictionaries 的 NSArray 内的值创建 UITableView 的索引

ios - Swift 2 中的 Parse.com 子类化

cocoa - 从计时器停止 NSRunLoop

macos - 更新 Homebrew 桶版本

macos - 如何通过 git clone 在 OSX 上构建和安装 node.js

objective-c - 第二个工具栏,如 NSScrollView 下的邮件 + 工具栏

ios - 错误 : Indexing expression is invalid because subscript type 'NSUInteger' is not an integral or objective c pointer type

macos - Cocoa:如何通过 Safari(不是默认浏览器)强制打开网站

objective-c - 如何使用 Objective-C 在自定义 View 中绘制文本?

ruby-on-rails - Ruby on Rails Beta 3 在 Snow Leopard 上安装 - 未找到文件