1

値を互いに同期させる必要がある 2 つの NSTextField コントロールを含むウィンドウがあります。具体的には、1 つは幅で、もう 1 つは長さであり、それらの比率は特定の縦横比に等しくなる必要があります。ユーザーが好きな方を設定し、もう一方を自動的に更新できるようにしたいと考えています。

私の最初のアプローチ: 2 つのコントロールのそれぞれのデリゲートをウィンドウ コントローラーに設定します。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 の状態を確認します。いいえの場合は、すぐに戻ります。YES の場合、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 に答える