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



我有一个tableView,有3列包含NSTextFieldCell。所有东西都被绑定填充。

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

有什么提示吗?


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

  • <尝试strong> # 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;
}
  • <尝试strong> # 2 :

子类NSTextFieldCell和覆盖drawWithFrame: inView: =>此方法仅用于在非编辑模式下绘制单元格。

  • <尝试strong> # 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;
}

在我看来,最好的方法是子类化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,它将无法正常工作。

希望这对你有帮助!

最新更新