协调一对 NSTextField 控件

Posted

技术标签:

【中文标题】协调一对 NSTextField 控件【英文标题】:Coordinating a pair of NSTextField controls 【发布时间】:2013-12-02 15:04:01 【问题描述】:

我有一个带有两个 NSTextField 控件的窗口,它们的值必须彼此保持同步。具体来说,一个是宽度,另一个是长度,它们的比例应该保持等于给定的纵横比。我希望用户能够设置他们喜欢的任何一个并自动更新另一个。

我的第一种方法:我将两个控件中的每一个的委托都设置为窗口控制器。我实现了 controlTextDidEndEditing 方法。我检查发件人。如果是宽度字段,我计算高度字段并通过绑定属性(self.my_height = self.my_width/aspectRatio)更新其值。同样,如果是高度字段,(self.my_width = self.my_height*aspectRatio)。

但我遇到了障碍。假设纵横比为 1.5。用户在宽度字段中输入 100,然后转到另一个字段。高度字段更新为 66(无论好坏,我选择始终向下舍入)。用户点击高度字段,不做任何改变,然后点击其他地方。宽度字段更新为 99。用户现在正在挠头。

我的改进。我还在窗口控制器中实现了 controlTextDidChange 方法。所有这一切都是将静态(文件范围)BOOL 变量 (gTextFieldDidChange) 设置为 YES。现在,当我进入 controlTextDidEndEditing 时,我检查 gTextFieldDidChange 的状态。如果否,那么我立即返回。如果是,那么我将 gTextFieldDidChange 清除回 NO 并处理长度/宽度更新。

这对我来说似乎没有任何问题,但它似乎相当“后门”。 我是否缺少更清洁/更智能的方法?

感谢任何/所有建议。 迈克

【问题讨论】:

我认为 Cocoa Bindings 正是您想要的 ;) 好的...我正在使用绑定来设置/访问代码和 UI 中的宽度/高度属性。当用户实际更改两个 NSTextField 控件之一时,如何将时间缩短为仅“同步”两者? @MikeMayer68 我只使用委托方法而不是绑定制作了一个小型演示应用程序,因为这是一个非常简单的案例。如果您有任何问题,请告诉我 ;-) 【参考方案1】:

以下代码使用NSTextFieldDelegate> 方法执行您想要的操作:

@interface HASMainViewController () <NSTextFieldDelegate>
@property (weak) IBOutlet NSTextField *widthTextField;
@property (weak) IBOutlet NSTextField *heightTextField;
@property (weak) IBOutlet NSTextField *ratioLabel;
@end

@implementation HASMainViewController

- (void)awakeFromNib 
    self.widthTextField.delegate = self;
    self.heightTextField.delegate = self;
    self.ratioLabel.stringValue = @"1.777777"; // 16:9 (1920 x 1080)


- (void)controlTextDidChange:(NSNotification *)obj 
    if (obj.object == self.widthTextField) 
        // If the width textfield gets changed we want to pass its value and -1 for calculating the height.
        // After that we set the height's text field to the calculated value.
        self.heightTextField.integerValue = [self calculateRatioComponentWithWidth:self.widthTextField.integerValue height:-1 ratio:self.ratioLabel.doubleValue];
     else if (obj.object == self.heightTextField) 
        // If the width textfield gets changed we want to pass its value and -1 for calculating the height.
        // After that we set the height's text field to the calculated value.
        self.widthTextField.integerValue = [self calculateRatioComponentWithWidth:-1 height:self.heightTextField.integerValue ratio:self.ratioLabel.doubleValue];
    


/**
 *  This method calculates the missing component (determined by "-1") for a given ratio.
 *
 *  @param width  An NSInteger representing the width. Pass -1 if this value should be calculated.
 *  @param height An NSInteger representing the height. Pass -1 if this value should be calculated.
 *  @param ratio  The ratio which needs to be kept.
 *
 *  @return An NSInteger which is depending on the what you passed as parameters the calculated width or height.
 *
 *  @discussion This method raises an HASInternalInconsistencyException exception if both width and height parameters are -1.
 *
 */
- (NSInteger)calculateRatioComponentWithWidth:(NSInteger)width height:(NSInteger)height ratio:(double)ratio 
    if (width == -1 && height == -1) [[NSException exceptionWithName:@"HASInternalInconsistencyException"
                                                              reason:@"Both width and height are -1 (to be calculated)."
                                                            userInfo:nil] raise];
    // Calculate new width
    if (width == -1) return (NSInteger)round(height * ratio);
    // Calculate new width
    else if (height == -1) return (NSInteger)round(width * 1 / ratio);
    // Just to silence the compiler
    return 0;


@end

您可以从我刚刚为您制作的Bitbucket Repository 克隆或下载一个小型示例应用程序;-)

【讨论】:

啊...我是如此接近,但错过了明显的。我试图使用宽度(或高度)属性的当前值来设置另一个。这失败了,因为直到调用 controlTextdidEndEditting 之前它才更新。我觉得自己像个傻瓜,没有考虑从控制本身中获取价值。 是的,你非常接近! 我似乎没有足够的声誉来支持答案。但我确实接受了。【参考方案2】:

我实际上找到了一个比我最初尝试和 HAS 建议的更好、更简单的解决方案。

我只是选中了值绑定下的“不断更新值”框。 这样做意味着绑定值在调用 controlTextDidChange 之前更新。

我现在可以在键入时进行更正,不再需要推迟到调用 controlTextDidEndEditting。

【讨论】:

以上是关于协调一对 NSTextField 控件的主要内容,如果未能解决你的问题,请参考以下文章

按 T​​ab 时 NSTextField 没有注意到失去焦点?

swift—UITextField与 NSTextView 的键盘事

具有多个控件的按键

将 NSTextField 绑定到 NSString

NSTextfield + NSMenu 和第一响应者

根据 Font/Size 改变 NSTextField 的高度