10

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が以下に提案するソリューション

ジョシュアのおかげで、これは私が探していたものに対する素晴らしい解決策です:

@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
4

1 に答える 1

7

フィールドが最初のレスポンダーになったときに、テキスト フィールドのフィールド エディターのプロパティを直接設定しないのはなぜですか?

典型的なテキスト フィールドでは、フィールドがファーストレスポンダーの場合にのみ選択が表示されるため、テキスト フィールドのフィールド エディターを要求して、その選択されたテキスト属性を設定すると、同じ効果が得られますよね?

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 の直接のスーパークラス) を返すと主張しています。フィールド エディターに NSTextView のみのメソッドを送信する予定の場合は、それを NSTextView としてキャストして、コンパイラの警告を抑える必要があります。メソッド プロトタイプが将来修正されても、キャストによってコード内の何も壊れないため、安全にそのままにしておくことができます。

于 2010-06-24T17:39:52.840 に答える