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

发布于 2024-11-27 14:19:46 字数 1629 浏览 4 评论 0原文

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

其中一列的单元格文本是经过计算的,并且不可直接编辑。 对于本专栏,我希望当单元格进入编辑模式时,显示按钮或自定义视图而不是文本字段
换句话说,我想要一个 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;
}

I have a tableView, with 3 columns containing NSTextFieldCell. Everything is populated with bindings.

The text of the cells of one of the column is computed and is not editable directly.
For this column, I would like when the cell goes into edit mode, to display a button or a custom view instead of the textField.
Said in an other way, I want an NSCell that is a NSTextFieldCell when not being edited, and a NSButtonCell (or a custom view) when being edited.

Any hint to move on to this?


Here is what I tried, without success:

  • Try #1:

I subclassed a NSTextFieldCell and override fieldEditorForView: like shown below => problem is the NSButton I'm returning does not respond to setDelegate: and probably many other stuff.

- (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;
}
  • Try #2:

Subclass NSTextFieldCell and override drawWithFrame: inView: => this method is only used to draw the cell when not in edit mode.

  • Try #3:

This lead has some potential, but I'm obviously missing something here.
Implement windowWillReturnFieldEditor: toObject: in my window's delegate, and return a custom field editor.
I seem to be on the right track, but I missed something. The argument anObject is never my custom cell (I double checked and it's defined properly in the 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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小嗲 2024-12-04 14:19:46

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

希望这有帮助!

It seems to me the best way to do this is to subclass NSTextView, making a new custom field editor for your custom cell, and then override - (NSTextView *)fieldEditorForView:(NSView *)aControlView in your custom cell to vend it. It looks like the expectation that an NSTextFieldCell's editor be an NSTextView is pretty much mandatory, which is probably why your attempt to return a button failed. I cooked up this brief example which displays a button, and when you press the button, it updates the value of the text field cell to the current time and ends editing. Maybe it'll be helpful:

@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

Then have your custom cell class do something like this:

@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

There are a couple of tricks here. First, as mentioned, as long as the cell is an NSTextFieldCell, the editor will have to be a subclass of NSTextView. Subclassing NSTextView brings with it a LOT of boilerplate behavior (you know, all the behaviors you normally want and get for free from using NSTextFieldCell for editing). If you want your app to NOT behave as if there's a text editor, you're going to end up doing some work to disable the normal behaviors of NSTextView.

Secondly, when you override - (NSTextView *)fieldEditorForView:(NSView *)aControlView it's important that it return the same field editor for the same cell across multiple calls. If you just create a new NSTextView on every call to that method, it will not work right.

Hope this helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文