2

NSTextFieldCell を含む 3 つの列を持つ tableView があります。すべてにバインディングが設定されています。

いずれかの列のセルのテキストは計算され、直接編集することはできません。この列では、セルが編集モードになったときに、 textField の代わりにボタンまたはカスタム ビューを表示したいと考えています。
別の言い方をすれば、編集されていないときはNSTextFieldCellであるNSCellが必要であり、編集されているときはNSButtonCell (またはカスタム ビュー) が必要です。

これに進むためのヒントはありますか?


これが私が試したものですが、成功しませんでした:

  • #1を試してください:

NSTextFieldCell以下に示すように aとオーバーライドをサブクラス化しましたfieldEditorForView:=> 問題は、返される NSButton が応答しないことsetDelegate:と、おそらく他の多くのものです。

- (NSTextView *)fieldEditorForView:(NSView *)aControlView {

    NSTableView *tableView = (NSTableView *) aControlView;

    // Manually computing column and row index for testing purposes
    NSButton* button = [[NSButton alloc] initWithFrame:[tableView frameOfCellAtColumn:2 row:2]];

    return (NSTextView *)button;
}
  • #2を試してください:

サブクラスNSTextFieldCellとオーバーライドdrawWithFrame: inView:=> このメソッドは、編集モードでないときにセルを描画するためにのみ使用されます。

  • #3を試してください:

この手がかりにはいくらかの可能性がありますが、明らかに何かが欠けています。
ウィンドウのデリゲートに実装windowWillReturnFieldEditor: toObject:し、カスタム フィールド エディターを返します。私は正しい軌道に乗っているように見えますが、何かを見逃していました。引数 anObject は決して私のカスタム セルではありません (再確認したところ、XIB で適切に定義されています)。

- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)anObject
{
    if ([anObject isKindOfClass:[NSCellTextAndButtonAtEditTime class]])
    {
        NSLog(@"Going there");

        NSButton* button = [[NSButton alloc] initWithFrame:CGRectMake(0, 0, 300, 20)];
        button.title = @"test";

        return button;
    }
    return nil;
}
4

1 に答える 1

2

これを行う最善の方法は、NSTextView をサブクラス化し、カスタム セル用の新しいカスタム フィールド エディタを作成してから、カスタム セルでオーバーライド- (NSTextView *)fieldEditorForView:(NSView *)aControlViewして販売することです。NSTextFieldCell のエディターが NSTextView であるという期待はほとんど必須であるように見えます。これがおそらく、ボタンを返そうとして失敗した理由です。ボタンを表示するこの簡単な例を作成しました。ボタンを押すと、テキスト フィールド セルの値が現在の時刻に更新され、編集が終了します。多分それは役に立つでしょう:

@interface SOMyEditor : NSTextView
@end

@interface SOMyEditor ()
- (void)p_buttonPressed: (id)sender;
@end

@implementation SOMyEditor

- (id)initWithFrame:(NSRect)frameRect textContainer:(NSTextContainer *)container;
{
    if (self = [super initWithFrame: frameRect textContainer:container])
    {
        NSButton* button = [[[NSButton alloc] initWithFrame: NSMakeRect(0,0,frameRect.size.width, frameRect.size.height)] autorelease];
        button.title = @"Update Time!";
        button.target = self;
        button.action = @selector(p_buttonPressed:);
        button.autoresizingMask |= NSViewWidthSizable | NSViewHeightSizable;
        self.autoresizesSubviews = YES;
        [self addSubview: button];
    }
    return self;
}

- (void)p_buttonPressed: (id)sender
{
    NSString* string = [[NSDate date] description];
    [self insertText: string];
    [self didChangeText];
    [self.window endEditingFor: self];
}

@end

次に、カスタム セル クラスに次のようなことをさせます。

@interface SOMyCustomTextFieldCell : NSTextFieldCell
@end

@interface SOMyCustomTextFieldCell ()
@property (retain) NSTextView* fieldEditor;
@end

@implementation SOMyCustomTextFieldCell
@synthesize fieldEditor = _fieldEditor;

- (NSTextView *)fieldEditorForView:(NSView *)aControlView
{
    if (nil == _fieldEditor)
    {
        _fieldEditor = [[SOMyEditor alloc] init];
        _fieldEditor.fieldEditor = YES;
    }

    return self.fieldEditor;    
}

- (void)dealloc
{
    [_fieldEditor release];
    [super dealloc];
}

@end

ここにはいくつかのトリックがあります。まず、前述のように、セルが NSTextFieldCell である限り、エディタは NSTextView のサブクラスである必要があります。NSTextView をサブクラス化すると、多くのボイラープレートの動作がもたらされます (編集に NSTextFieldCell を使用することで、通常必要なすべての動作を無料で取得できます)。アプリをテキスト エディターのように動作させたくない場合は、NSTextView の通常の動作を無効にする作業を行うことになります。

第 2 に、オーバーライドするときは、複数の呼び出しで同じセルに対して同じ- (NSTextView *)fieldEditorForView:(NSView *)aControlViewフィールド エディターを返すことが重要です。そのメソッドを呼び出すたびに新しい NSTextView を作成しただけでは、正しく機能しません。

お役に立てれば!

于 2012-01-14T22:42:39.720 に答える