如何创建NSTextFieldCell,在编辑模式下显示自定义视图而不是NSTextField?

时间:2011-08-01 18:27:04

标签: cocoa nscell nstextfieldcell nstableviewcell nsbuttoncell

我有一个tableView,其中3列包含NSTextFieldCell。一切都装满了绑定。

计算其中一列的单元格文本,并且不能直接编辑。 对于此列,我希望当单元格进入编辑模式时,显示按钮或自定义视图而不是textField
换句话说,我想要一个 NSCell ,当没有被编辑时是一个 NSTextFieldCell ,一个 NSButtonCell (或一个自定义视图)正在编辑。

有什么提示可以继续吗?


这是我尝试过的,没有成功:

  • 尝试#1

我将NSTextFieldCell子类化并覆盖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;
}

1 个答案:

答案 0 :(得分: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的正常行为。

其次,当您覆盖- (NSTextView *)fieldEditorForView:(NSView *)aControlView时,重要的是它会在多个调用中为同一个单元格返回相同的字段编辑器。如果您只是在每次调用该方法时创建一个新的NSTextView,它将无法正常工作。

希望这有帮助!