【问题标题】:NSTextField with Number Formatter not allowing decimal input带有数字格式化程序的 NSTextField 不允许十进制输入
【发布时间】:2012-01-26 19:51:03
【问题描述】:

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

头文件在这里:

#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

【问题讨论】:

    标签: objective-c cocoa interface-builder nstextfield


    【解决方案1】:

    这有点晦涩难懂,但是您尝试做的事情并不能真正奏效,但是有替代方法。

    在您的代码中:

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

    第一行请求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)];
       }
    }
    

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

    这个解决方案不如你尝试的那样“动态”,但它确实有效。要恢复动态响应,您需要编写更多涉及的代码,如上所述。

    【讨论】:

    • 所以我对您建议的不太动态的方法进行了更改,它确实允许我输入十进制数字。问题? - 如何格式化文本字段,使其显示有效数字,例如 45 将显示为 45.00
    • 如果您能给出示例代码说明我如何正确动态地实现这一点,我将不胜感激。
    • @Gavin:您可以查看NSNumberFormatter 上的setMinimumFractionDigits: 之类的方法(并且您可以使用NSTextFieldformatter 方法获得正在使用的格式化程序)。您可能很想将这些方法(其中一种用于小数点显示)与动态方法一起使用,但您会得到非常奇怪的行为,因为您将在用户键入时更改用户键入的内容并且光标不会他们认为它在哪里......
    • @Gavin:关于第二条评论,这是您必须自己弄清楚的事情!考虑到您必须不仅允许“1”。作为有效输入,但也可能是“1”,然后再等待 3 个数字......如果第一个字段中有“2,34”,你会在第二个字段中显示什么?我相信你可以做一些事情,但语义/启发式是不平凡的。
    • 好的,我得到了格式化工作。我将把动态更新留到另一天。所以最后一个问题 - 当我在文本框中单击(单击而不是双击)时,如何使文本字段突出显示所有内容?我知道有一个 [NSTextField selectText:] 方法,但我不确定如何在我的代码中使用它。
    【解决方案2】:

    我知道我回答得太晚了,但我遇到了完全相同的问题并找到了一个很好的解决方法。以@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
        }
    }
    

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

    【讨论】:

      【解决方案3】:

      聚会有点晚了,但我自己也遇到了这个问题,我想我找到了一个简洁的解决方案,可以保持动态更新,同时避免格式化程序过早启动,从而阻止用户输入分数:

      - (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)];
         }
      }
      

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

      【讨论】:

        猜你喜欢
        • 2016-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-13
        • 2021-10-22
        • 1970-01-01
        • 2022-01-05
        相关资源
        最近更新 更多