带数字格式化的NSTextField不允许十进制输入

时间:2012-01-26 19:51:03

标签: objective-c cocoa interface-builder nstextfield

我正在尝试创建一个简单的Cocoa应用程序,其中数字输入到文本字段中。当一个数字键入一个文本字段时,另一个文本字段将自动更新另一个数字(反之亦然)。我拖到窗口中的文本字段是界面构建器中的“带数字格式化器的文本字段”。我将textfields设置为委托,允许它们自动更新。但是,格式似乎不起作用。我无法输入十进制数字。请帮忙!!!

此处的头文件:

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate> {
    IBOutlet NSTextField *number1;
    IBOutlet NSTextField *number2;
}

@property (assign) IBOutlet NSWindow *window;

@end

此处的实施文件:

#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window = _window;

-(void)controlTextDidChange:(NSNotification *) note {
    NSTextField *changedField = [note object];

    if (changedField == number1) {
        float num1 = [number1 floatValue];
        [number2 setFloatValue: (num1*2.0)];
    }

    if (changedField == number2) {
        float num2 = [number2 floatValue];
        [number1 setFloatValue: (num2/2.0)];
    }
}

@end

3 个答案:

答案 0 :(得分:1)

这有点模糊,但你想要做的事情不能真正起作用,但还有另一种选择。

在您的代码中,您有:

float num1 = [number1 floatValue];
[number2 setFloatValue: (num1*2.0)];

第一行请求{em>当前值number1。由于您有一个数字格式化程序附加到number1,因此系统会调用格式化文本格式...如果您此时输入了123.,则格式化结果为123。 ..并且你的小数点消失了。你会注意到你不能输入逗号(千位分隔符)。

因此,基本问题是在输入每个字符后,您的代码会强制它在此时成为有效数字

另一种方法是仅在用户输入完整号码时执行操作。你可以自己编写代码来分析每个字符输入时的输入,也可以使用快速简便的方法等待用户点击并响应操作。

要做到后者,请将代码更改为:

- (IBAction) textDidChange:(id)sender
{
   if (sender == number1)
   {
      float num1 = [number1 floatValue];
      [number2 setFloatValue: (num1*2.0)];
   }
   else if (sender == number2)
   {
      float num2 = [number2 floatValue];
      [number1 setFloatValue: (num2/2.0)];
   }
}

并将其作为“选择器”连接到控件,并删除已有的“委托”连接。

此解决方案不像您尝试的那样“动态”,但确实有效。要获得动态响应,您需要编写更多涉及的代码,如上所述。

答案 1 :(得分:1)

我知道我回答的时间已经很晚了,但我遇到了同样的问题并找到了一个很好的解决方法。以@ CRD的答案为基础。

我是如何完成这个问题的:

  • 存储格式化程序
  • 从文本字段中擦除格式化程序
  • 从文本字段中读取值
  • 将格式化程序重新应用于文本字段

我如何做到的一个例子如下:

-(void)controlTextDidChange:(NSNotification *)obj
{
    if ([obj object])
    {
        NSTextField *field = [obj object];
        NSNumberFormatter *formatter = [field formatter];
        [field setFormatter:nil];
        double data = [field doubleValue];
        [field setFormatter:formatter];
        // ...
        // Do other meaningful stuff now
    }
}

不确定这是否是正确的方法,但对我来说效果很好。

答案 2 :(得分:0)

派对有点晚了,但我自己也遇到了这个问题,我想我发现了一个简洁的解决方案,可以保持动态更新,同时避免格式化程序过早地开始,从而阻止用户输入分数:< / p>

- (void)controlTextDidChange:(NSNotification *)aNotification
{
    NSTextView *fieldEditor = [aNotification.userInfo valueForKey:@"NSFieldEditor"];
    CGFloat floatValue = fieldEditor.textStorage.string.floatValue;
    // Getting the new value from the field editor avoids the formatter kicking in here.
    // You can now use the value as you wish. Probably something like:
   if (sender == number1)
   {
      [number2 setFloatValue: (floatValue*2.0)];
   }
   else if (sender == number2)
   {
      [number1 setFloatValue: (floatValue/2.0)];
   }
}

(我把它输入浏览器,所以它可能不完全正确,但应该足够接近。基本部分是前两行:提取字段编辑器并从中提取新值。