当NSTextField按Tab键失去焦点时,我似乎找不到通知的方法。单击另一个控件或按Enter键时,我得到了一个很好的 textDidEndEditing ,但是如果我通过按Tab键更改焦点则没有。
还试图为此目的猛拉 KeyDown 和 doCommandBySelector ,但我无处可去。
有什么想法吗?
提前致谢
修改
忘了提,但我也尝试了resignFirstResponder。这是我试过的代码:
- (BOOL)resignFirstResponder
{
NSRunAlertPanel(@"", @"Lost Focus",@"OK", nil, nil);
return [super resignFirstResponder];
}
- (BOOL)becomeFirstResponder
{
NSRunAlertPanel(@"", @"Got focus",@"OK", nil, nil);
return [super becomeFirstResponder];
}
奇怪的是,这里发生的事情是,当获得焦点时,一个接一个地调用firstFirstResponder和resignFirstResponder。但是当将焦点从控制中移开时,两者都不是。
答案 0 :(得分:6)
"我得到了一个很好的textDidEndEditing 单击另一个控件或何时 按Enter键,但如果我改变则不行 按Tab键即可获得焦点。"
截至2011年4月,使用OS X 10.6库,我使用:
- (void)controlTextDidEndEditing:(NSNotification *)aNotification
...听取NSTextField失去焦点,并且它正常工作。在你的情况下这可能吗?它是否曾经被打破,但现在由Apple修复?
如果是这样,它的代码要少得多:)。
答案 1 :(得分:2)
好的,我找到了一种方法:使用窗口委托使窗口返回自定义字段编辑器。此字段编辑器会跟踪最后一个已激活的TextField,并在丢失firstResponder本身时调用其textDidEndEditting方法。以下是如何执行此操作的示例:
#import <Cocoa/Cocoa.h>
#import <AppKit/AppKit.h>
@interface MyTextField : NSTextField
- (BOOL)resignFirstResponder;
- (void)textDidEndEditing:(NSNotification *)notification;
@end
@interface MyFieldEditor : NSTextView
{
MyTextField * lastBox;
}
-(void) setLastEditBox:(MyTextField*) box;
@end
@interface MyWindowDelegate : NSWindowController
{
MyFieldEditor *fieldEditor;
}
@end
@implementation MyFieldEditor
-(void) setLastEditBox:(MyTextField*) box{ lastBox = box; }
-(id)init
{
if (self = [super init])
[self setFieldEditor:YES];
return self;
}
- (BOOL)resignFirstResponder
{
// Activate the last active editbox editting-end event
if(lastBox != nil)
{
[lastBox textShouldEndEditing:self];
lastBox = nil;
}
return [super resignFirstResponder];
}
@end
@implementation MyWindowDelegate
-(id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)client
{
if(fieldEditor == nil) // Return our special field editor
fieldEditor = [[[MyFieldEditor alloc] autorelease] init];
return fieldEditor;
}
@end
@implementation MyTextField
- (BOOL)resignFirstResponder
{
// We're losing first responder, inform the field editor that this was the last edit box activated
MyFieldEditor* myTf = (MyFieldEditor*) [[self window] fieldEditor:YES forObject:self];
[myTf setLastEditBox:self];
return [super resignFirstResponder];
}
- (void)textDidEndEditing:(NSNotification *)notification;
{
[super textDidEndEditing:notification];
[self setStringValue:@"RECEIVED ENDEDITING"];
}
@end
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSApplication *app = [NSApplication sharedApplication];
NSRect frame = NSMakeRect(100, 100, 200, 150);
// Create the window
NSWindow* window = [[[NSWindow alloc] autorelease ] initWithContentRect:frame styleMask:NSClosableWindowMask|NSResizableWindowMask
backing:NSBackingStoreBuffered defer:NO];
[window setDelegate:[[MyWindowDelegate alloc] autorelease]];
MyTextField * tf = [ [[ MyTextField alloc ] autorelease] initWithFrame: NSMakeRect( 30.0, 100.0, 150.0, 22.0 ) ];
[ [ window contentView ] addSubview: tf ];
MyTextField * tf2 = [ [[ MyTextField alloc ] autorelease] initWithFrame: NSMakeRect( 30.0, 40.0, 150.0, 22.0 ) ];
[ [ window contentView ] addSubview: tf2 ];
[window makeKeyAndOrderFront: window];
[app run];
[pool release];
return 0;
}
答案 2 :(得分:2)
你必须只做这个
对于关键标签
self.textfield.delegate = self;
然后实现此方法
- (void)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector
{
NSLog(@"Selector method is (%@)", NSStringFromSelector( commandSelector ) );
if (commandSelector == @selector(insertTab:)) {
//Do something against TAB key
//Or Call a Method
}
}
或者看看我的回答 Execute an Action when the Enter-Key is pressed in a NSTextField?
答案 3 :(得分:0)
根据我在其他帖子中提到的理解,我找到了答案。这有点令人费解,但它确实有效。您必须继承NSTextField和NSWindow的子类,因为您需要两者的信息来设置它。这是子类: HMTextField.h
#import <Foundation/Foundation.h>
@interface HMTextField : NSTextField {
}
@end
HMTextField.m
#import "HMTextField.h"
#import "HMWindow.h"
@implementation HMTextField
- (BOOL)becomeFirstResponder {
[(HMWindow*)[self window] setTfBecameFirstResponder:YES];
return [super becomeFirstResponder];
}
@end
HMWindow.h
#import <Foundation/Foundation.h>
@interface HMWindow : NSWindow {
BOOL tfIsFirstResponder, tfBecameFirstResponder;
}
@property (nonatomic, readwrite, assign) BOOL tfBecameFirstResponder;
@end
HMWindow.m
#import "HMWindow.h"
@implementation HMWindow
@synthesize tfBecameFirstResponder;
-(id)init {
if (self = [super init]) {
tfIsFirstResponder = NO;
}
return self;
}
- (NSResponder *)firstResponder {
id fr = [super firstResponder];
if ([fr isEqualTo:[self fieldEditor:NO forObject:nil]]) {
tfIsFirstResponder = YES;
} else {
if (tfIsFirstResponder && tfBecameFirstResponder) {
NSLog(@"the text field stopped being first responder");
tfBecameFirstResponder = NO;
}
tfIsFirstResponder = NO;
}
return fr;
}
@end
制作课程并使你的对象成为他们的课程。您将从文本字段中收到第一个响应者更改的通知,其中NSLog消息位于HMWindow.m文件中。如果您需要帮助,了解它是如何工作的,请告诉我。
答案 4 :(得分:0)
这是一个如何指示自定义NSTextFieldCell(NSCell)应该绘制自己的边框和时间的适当时间的示例。聚焦环(在方法[NSTextFieldCell drawWithFrame:inView]中),通过'借用'单元格的高亮区域,在文本字段获得焦点时设置它,并在文本字段失去焦点时清除它(编辑完成)。
这种技术克服了一些问题:
由于我们重新设置了单元格的“突出显示”状态字段,为了将焦点状态传递给单元格,请确保从自定义NSTextFieldCell的[highlightColorWithFrame:inView:]方法返回nil。
#import "CustomTextField.h"
@implementation CustomTextField
-(BOOL)becomeFirstResponder {
((NSTextFieldCell *)self.cell).highlighted = true;
return [super becomeFirstResponder];
}
-(void)textDidEndEditing:(NSNotification *)notification {
((NSTextFieldCell *)self.cell).highlighted = false;
[super textDidEndEditing:notification];
}
@end
答案 5 :(得分:0)
复杂的答案。有一种更简单的方法。
不要忘记将NSTextField子类化为NotificableTextField并将其委托设置为您的视图控制器。
<强> NotificableTextField.h 强>:
#import <Cocoa/Cocoa.h>
@protocol NotificableTextFieldDelegate <NSObject>
@optional
- (void)textFieldStartedEditing:(NSTextField *)textField;
- (void)textFieldEndedEditing:(NSTextField *)textField;
@end
@interface NotificableTextField : NSTextField
@end
<强> NotificableTextField.m 强>:
#import "NotificableTextField.h"
@implementation NotificableTextField
- (void)awakeFromNib
{
[super awakeFromNib];
self.target = self;
self.action = @selector(inputEnd);
}
- (BOOL)becomeFirstResponder
{
BOOL status = [super becomeFirstResponder];
if (status && [self.delegate respondsToSelector:@selector(textFieldStartedEditing:)])
[(id<NotificableTextFieldDelegate>)self.delegate textFieldStartedEditing:self];
return status;
}
- (void)inputEnd
{
if ([self.delegate respondsToSelector:@selector(textFieldEndedEditing:)])
[(id<NotificableTextFieldDelegate>)self.delegate textFieldEndedEditing:self];
}
@end
答案 6 :(得分:-1)
NSTextField是NSResponder的子类。 NSResponder有一个方法 - (BOOL)resignFirstResponder。当NSTextField不再是第一响应者时,这将通知您...即。失去焦点。所以继承你的NSTextField并在那里做你的东西。