1

我有一个带有两个 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 并处理长度/宽度更新。

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

感谢您的任何/所有建议。麦克风

4

2 回答 2

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 存储库中克隆或下载一个小型示例应用程序;-)

于 2013-12-03T21:20:27.217 回答
0

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

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

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

于 2014-01-04T02:08:22.597 回答