0

我找不到一个简单的例子来说明如何使用 NSTextField 来编辑它的内容。

就像在 Finder 中一样 - 您可以单击,并且在短暂的延迟之后,文本字段变为可编辑。

它似乎是 textField、它的单元格和 fieldEditor 的某种组合?问题是我找不到如何做到这一点的最基本的例子。

我尝试使用几个不同的测试对 NSTextField 进行子类化,但它没有奏效:

#import "GWTextField.h"
@implementation GWTextField
- (id) initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    return self;
}
- (void) mouseDown:(NSEvent *)theEvent {
    [super mouseDown:theEvent];
    [self.cell editWithFrame:self.frame inView:self.superview editor:[self.cell fieldEditorForView:self] delegate:self event:theEvent];
    //[self setEditable:TRUE];
    //[self setSelectable:TRUE];
    //[self selectText:nil];
    [NSTimer scheduledTimerWithTimeInterval:.3 target:self selector:@selector(edit:) userInfo:nil repeats:FALSE];
}
- (void) edit:(id) sende {
    NSLog(@"edit");
    [[NSApplication sharedApplication].mainWindow makeFirstResponder:self];
    [self selectText:nil];
}
@end

有任何想法吗?

4

4 回答 4

3

这是另一个没有 NSCell 的解决方案 - 一位用户指出 NSCell 已被弃用,并且会在某个时候消失。

#import <Cocoa/Cocoa.h>

@interface EditTextField : NSTextField <NSTextDelegate,NSTextViewDelegate,NSTextFieldDelegate>

@property BOOL isEditing;
@property BOOL commitChangesOnEscapeKey;
@property BOOL editAfterDelay;
@property CGFloat delay;

@end

----


#import "EditTextField.h"

@interface EditTextField ()
@property NSObject <NSTextFieldDelegate,NSTextViewDelegate> * userDelegate;
@property NSString * originalStringValue;
@property NSTimer * editTimer;
@property NSTrackingArea * editTrackingArea;
@end

@implementation EditTextField

- (id) initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    [self defaultInit];
    return self;
}

- (id) initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    [self defaultInit];
    return self;
}

- (id) init {
    self = [super init];
    [self defaultInit];
    return self;
}

- (void) defaultInit {
    self.delay = .8;
}

- (void) mouseDown:(NSEvent *) theEvent {
    if(theEvent.clickCount == 2) {
        [self startEditing];
    } else {
        [super mouseDown:theEvent];
        if(self.editAfterDelay) {
            [self startTracking];
            self.editTimer = [NSTimer scheduledTimerWithTimeInterval:.8 target:self selector:@selector(startEditing) userInfo:nil repeats:FALSE];
        }
    }
}

- (void) startTracking {
    if(!self.editTrackingArea) {
        self.editTrackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:NSTrackingMouseEnteredAndExited|NSTrackingMouseMoved|NSTrackingActiveInActiveApp|NSTrackingAssumeInside|NSTrackingInVisibleRect owner:self userInfo:nil];
    }
    [self addTrackingArea:self.editTrackingArea];
}

- (void) mouseExited:(NSEvent *)theEvent {
    [self.editTimer invalidate];
    self.editTimer = nil;
}

- (void) mouseMoved:(NSEvent *) theEvent {
    [self.editTimer invalidate];
    self.editTimer = nil;
}

- (void) startEditing {
    id firstResponder = self.window.firstResponder;
    if([firstResponder isKindOfClass:[NSTextView class]]) {
        NSTextView * tv = (NSTextView *)firstResponder;
        if(tv.delegate && [tv.delegate isKindOfClass:[EditTextField class]]) {
            EditTextField * fr = (EditTextField *)tv.delegate;
            [fr stopEditingCommitChanges:FALSE clearFirstResponder:FALSE];
        }
    }
    if(self.delegate != self) {
        self.userDelegate = (NSObject <NSTextFieldDelegate,NSTextViewDelegate> *)self.delegate;
    }
    self.isEditing = TRUE;
    self.delegate = self;
    self.editable = TRUE;
    self.originalStringValue = self.stringValue;
    [self.window makeFirstResponder:self];
}

- (void) stopEditingCommitChanges:(BOOL) commitChanges clearFirstResponder:(BOOL) clearFirstResponder {
    self.editable = FALSE;
    self.isEditing = FALSE;
    self.delegate = nil;
    [self removeTrackingArea:self.editTrackingArea];
    if(!commitChanges) {
        self.stringValue = self.originalStringValue;
    }
    if(clearFirstResponder) {
        [self.window makeFirstResponder:nil];
    }
}

- (void) cancelOperation:(id) sender {
    if(self.commitChangesOnEscapeKey) {
        [self stopEditingCommitChanges:TRUE clearFirstResponder:TRUE];
    } else {
        [self stopEditingCommitChanges:FALSE clearFirstResponder:TRUE];
    }
}

- (BOOL) textView:(NSTextView *) textView doCommandBySelector:(SEL) commandSelector {
    BOOL handlesCommand = FALSE;
    NSString * selector = NSStringFromSelector(commandSelector);

    if(self.userDelegate) {

        if([self.userDelegate respondsToSelector:@selector(control:textView:doCommandBySelector:)]) {
            handlesCommand = [self.userDelegate control:self textView:textView doCommandBySelector:commandSelector];
        } else if([self.userDelegate respondsToSelector:@selector(textView:doCommandBySelector:)]) {
            handlesCommand = [self.userDelegate textView:textView doCommandBySelector:commandSelector];
        }

        if(!handlesCommand) {

            if([selector isEqualToString:@"insertNewline:"]) {
                [self stopEditingCommitChanges:TRUE clearFirstResponder:TRUE];
                handlesCommand = TRUE;
            }

            if([selector isEqualToString:@"insertTab:"]) {
                [self stopEditingCommitChanges:TRUE clearFirstResponder:FALSE];
                handlesCommand = FALSE;
            }
        }

    } else {

        if([selector isEqualToString:@"insertNewline:"]) {
            [self stopEditingCommitChanges:TRUE clearFirstResponder:TRUE];
            handlesCommand = TRUE;
        }

        if([selector isEqualToString:@"insertTab:"]) {
            [self stopEditingCommitChanges:TRUE clearFirstResponder:FALSE];
            handlesCommand = FALSE;
        }
    }

    return handlesCommand;
}

@end
于 2015-04-22T21:23:09.517 回答
0

我构建了一个可重用的 NSTextField 子类,您可以将其用于就地编辑功能。http://pastebin.com/QymunMYB

于 2014-04-22T17:27:16.220 回答
0

我想出了一个更好的解决就地编辑问题的方法。我相信这是使用 NSCell 正确进行编辑的方法。请显示并判断这是否是错误的。

#import <Cocoa/Cocoa.h>
@interface EditTextField : NSTextField <NSTextDelegate>
@end

---

#import "EditTextField.h"

@implementation EditTextField

- (void) mouseDown:(NSEvent *)theEvent {
    if(theEvent.clickCount == 2) {
        self.editable = TRUE;
        NSText * fieldEditor = [self.window fieldEditor:TRUE forObject:self];
        [self.cell editWithFrame:self.bounds inView:self editor:fieldEditor delegate:self event:theEvent];
    } else {
        [super mouseDown:theEvent];
    }
}

- (void) cancelOperation:(id)sender {
    [self.cell endEditing:nil];
    self.editable = FALSE;
}

- (BOOL) textView:(NSTextView *) textView doCommandBySelector:(SEL) commandSelector {
    NSString * selector = NSStringFromSelector(commandSelector);
    if([selector isEqualToString:@"insertNewline:"]) {
        NSText * fieldEditor = [self.window fieldEditor:TRUE forObject:self];
        [self.cell endEditing:fieldEditor];
        self.editable = FALSE;
        return TRUE;
    }
    return FALSE;
}

@end
于 2015-04-22T01:08:28.720 回答
0

在我的应用程序中,我有两个文本字段 - 一个不可编辑,第二个是隐藏的、可编辑的,并通过调用激活标题编辑:

[self addSubview:windowTitle];
[windowTitleLabel removeFromSuperview]; 
[self.window makeFirstResponder:windowTitle];   

这是从 mouseUp: 在标签后面的视图中调用的。

我不记得为什么我需要有两个文本字段(我当时不太了解 Cocoa),即使没有标签交换它也可能会工作。

于 2014-04-19T16:00:49.103 回答