gpt4 book ai didi

macos - 如何检测 NSTextField 何时获得焦点或者其内容是否被选中 cocoa

转载 作者:行者123 更新时间:2023-12-03 16:06:19 25 4
gpt4 key购买 nike

我在 NSTableCellView 中有一个 NSTextField,我想要一个事件,当我的 NSTextField 获得焦点以禁用多个按钮时通知我,我找到了这个方法:

-(void)controlTextDidBeginEditing:(NSNotification *)obj{
NSTextField *textField = (NSTextField *)[obj object];

if (textField != _nombreDelPaqueteTextField) {
[_nuevaCuentaActivoButton setEnabled:FALSE];
[_nuevaCuentaPasivoButton setEnabled:FALSE];
[_nuevaCuentaIngresosButton setEnabled:FALSE];
[_nuevaCuentaEgresosButton setEnabled:FALSE];
}
}

但它会在我的文本字段开始编辑时触发,如下所示,我希望当我将焦点放在文本字段上时禁用按钮,而不是当我已经开始输入时

<小时/>

编辑:将根据Joshua Nozzi收到的帮助放置我的代码,但它仍然不起作用

MyNSTextField.h

#import <Cocoa/Cocoa.h>
@class MyNSTextField;

@protocol MyNSTextFieldDelegate

@optional -(BOOL)textFieldDidResignFirstResponder:(NSTextField *)sender;
@optional -(BOOL)textFieldDidBecomeFirstResponder:(NSTextField *)sender;

@end

@interface MyNSTextField : NSTextField

@property (strong, nonatomic) id <MyNSTextFieldDelegate> cellView;

@end

MyNSTextField.m

#import "MyNSTextField.h"

@implementation MyNSTextField

- (BOOL)becomeFirstResponder
{
BOOL status = [super becomeFirstResponder];
if (status)

[self.cellView textFieldDidBecomeFirstResponder:self];
return status;
}

- (BOOL)resignFirstResponder
{
BOOL status = [super resignFirstResponder];
if (status)
[self.cellView textFieldDidResignFirstResponder:self];
return status;
}

@end

在我的 View Controller EdicionDeCuentasWC.m

#import "MyNSTextField.h"


@interface EdicionDeCuentasWC ()<NSTableViewDataSource, NSTableViewDelegate, NSControlTextEditingDelegate, NSPopoverDelegate, MyNSTextFieldDelegate>
@end


@implementation EdicionDeCuentasWC
#pragma mark MyNSTextFieldDelegate
-(BOOL)textFieldDidBecomeFirstResponder:(NSTextField *)sender{
NSLog(@"textFieldDidBecomeFirstResponder");
return TRUE;
}

-(BOOL)textFieldDidResignFirstResponder:(NSTextField *)sender{
NSLog(@"textFieldDidResignFirstResponder");
return TRUE;
}
#pragma mark --
@end

重要的是在可视化编辑器中,已经将我的所有 NSTextField 更改为 MyNSTextField 类并将委托(delegate)设置为我的文件所有者 (EdicionDeCuentasWC)

最佳答案

我想我已经成功了。我试图子类化 NSTextFiled 来覆盖 becomeFirstResponder()resignFirstResponder(),但是一旦我单击它,becomeFirstResponder() 被调用,然后 resignFirstResponder() 被调用。啊?但搜索字段看起来仍在编辑中,焦点仍在其上。

我发现,当您单击搜索字段时,搜索字段会成为第一响应者一次,但是 NSText 会在稍后的某个地方准备好,并且焦点将移动到 NSText .

我发现当 NSText 准备好时,它被设置为 self.currentEditor() 。问题是,当调用 becomeFirstResponder() 时,self.currentEditor() 尚未设置。所以 becomeFirstResponder() 不是检测焦点的方法。

另一方面,当焦点移动到 NSText 时,文本字段的 resignFirstResponder() 被调用,你知道吗? self.currentEditor() 已设置。因此,现在是告诉它的委托(delegate)该文本字段获得焦点的时刻。

接下来,如何检测搜索字段何时失去焦点。再说一遍,这是关于 NSText 的。然后,您需要监听 NSText 委托(delegate)的方法,例如 textDidEndEditing(),并确保让其父类(super class)处理该方法,并查看是否 self.currentEditor( ) 无效。如果是这种情况,NSText 会失去焦点并告知文本字段的委托(delegate)。

我提供了一段代码,实际上是NSSearchField子类来做同样的事情。同样的原理也适用于 NSTextField

protocol ZSearchFieldDelegate: NSTextFieldDelegate {
func searchFieldDidBecomeFirstResponder(textField: ZSearchField)
func searchFieldDidResignFirstResponder(textField: ZSearchField)
}


class ZSearchField: NSSearchField, NSTextDelegate {

var expectingCurrentEditor: Bool = false

// When you clicked on serach field, it will get becomeFirstResponder(),
// and preparing NSText and focus will be taken by the NSText.
// Problem is that self.currentEditor() hasn't been ready yet here.
// So we have to wait resignFirstResponder() to get call and make sure
// self.currentEditor() is ready.

override func becomeFirstResponder() -> Bool {
let status = super.becomeFirstResponder()
if let _ = self.delegate as? ZSearchFieldDelegate where status == true {
expectingCurrentEditor = true
}
return status
}

// It is pretty strange to detect search field get focused in resignFirstResponder()
// method. But otherwise, it is hard to tell if self.currentEditor() is available.
// Once self.currentEditor() is there, that means the focus is moved from
// serach feild to NSText. So, tell it's delegate that the search field got focused.

override func resignFirstResponder() -> Bool {
let status = super.resignFirstResponder()
if let delegate = self.delegate as? ZSearchFieldDelegate where status == true {
if let _ = self.currentEditor() where expectingCurrentEditor {
delegate.searchFieldDidBecomeFirstResponder(self)
// currentEditor.delegate = self
}
}
self.expectingCurrentEditor = false
return status
}

// This method detect whether NSText lost it's focus or not. Make sure
// self.currentEditor() is nil, then that means the search field lost its focus,
// and tell it's delegate that the search field lost its focus.

override func textDidEndEditing(notification: NSNotification) {
super.textDidEndEditing(notification)

if let delegate = self.delegate as? ZSearchFieldDelegate {
if self.currentEditor() == nil {
delegate.searchFieldDidResignFirstResponder(self)
}
}
}

}

您需要将 NSSerachField 更改为 ZSearchField,并且您的客户端类必须符合 ZSearchFieldDelegate 而不是 NSTextFieldDelegate 。这是一个例子。当用户单击搜索字段时,它会扩展其宽度,而当您单击其他位置时,通过更改 Interface Builder 设置的 NSLayoutConstraint 值,搜索字段会失去焦点并缩小其宽度。

class MyViewController: NSViewController, ZSearchFieldDelegate {

// [snip]

@IBOutlet weak var searchFieldWidthConstraint: NSLayoutConstraint!

func searchFieldDidBecomeFirstResponder(textField: ZSearchField) {
self.searchFieldWidthConstraint.constant = 300
self.view.layoutSubtreeIfNeeded()
}

func searchFieldDidResignFirstResponder(textField: ZSearchField) {
self.searchFieldWidthConstraint.constant = 100
self.view.layoutSubtreeIfNeeded()
}

}

这可能取决于操作系统的行为,我在 El Capitan 10.11.4 上尝试过,并且成功了。

代码也可以从 Gist 复制。 https://gist.github.com/codelynx/aa7a41f5fd8069a3cfa2

关于macos - 如何检测 NSTextField 何时获得焦点或者其内容是否被选中 cocoa ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25692122/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com