【问题标题】:Error check kicks in even before entire value is entered in an edit box甚至在将整个值输入到编辑框中之前,错误检查就开始了
【发布时间】:2016-03-09 22:55:00
【问题描述】:

我在一个表单上有两个编辑框,一个用于最小值,另一个用于用户需要输入的最大值。我想在用户输入值时捕获可能的错误。一种可能的错误是最大值小于最小值。如果发生这种情况,我会显示一条错误消息。但是,即使用户想在最小值框中输入 5,在最大值框中输入 100,即使用户在最大值框中输入 100 的“1”,如果他已经在最小值框中输入了 5。如何让用户在弹出错误消息之前输入整个值?

这是我的代码(我也发现了其他错误,但似乎只有 max

procedure TfrmAnalysisOptions.lbleConstraintsMaxChange(Sender: TObject);
var
  I: integer;
  Val, ValidEntry: string;
  Chr: char;
  RangeMin, RangeMax: Double;
  const Allowed = ['0'..'9', '.'];
begin

  Val := lbleConstraintsMax.Text;

      //initialize values    
  ValidEntry := '';
  ConstraintsMaxChange := '';

  //value can contain only numerals, and "."
    for I := 1 to Length(Val) do
     begin
       Chr := Val[I];
       if not (Chr in Allowed) then
       begin
     MessageDlgPos('The value entered for the max value of the ' +
               'constraint must contain only a numeral, a decimal ' +
               'point or a negative sign.',
            mtError, [mbOK], 0, 300, 300);
     Exit;

       end
       else ValidEntry := 'OK'; //validity check for this part

     end;

     //max value cannot be zero or less than the min value
    if not TryStrToFloat(Val, RangeMax) then Exit
    else if RangeMax = 0 then
    begin
       MessageDlg('Max value cannot be zero.', mtError, [mbOK], 0);
       Exit;
    end
    else if not TryStrToFloat(lbleConstraintsMin.Text, RangeMin) then Exit
    else if RangeMax < RangeMin then
      begin
    MessageDlgPos('Max value cannot be less than Min value.',
           mtError, [mbOK], 0, 300, 300);
    Exit;
      end

    else if (RangeMax < 0) then
      begin
    MessageDlgPos('A constraint cannot be negative.',
              mtError, [mbOK], 0, 300, 300);
    Exit;
      end

    //final validity check
    else if ValidEntry = 'OK' then ConstraintsMaxChange := 'OK'
    else MessageDlgPos('There was an unexpected problem with the ' +
               'value entered in the max constraints box.',
            mtError, [mbOK], 0, 300, 300);

end;

【问题讨论】:

  • TMaskEdit 组件允许屏蔽输入字符。掩码###.# 会阻止除数字和十进制字符之外的任何内容。
  • 谢谢,@LURD。让我检查一下,因为减号也是有效的。
  • # 也允许签名。
  • @LURD ###.##.# 有区别吗?
  • @JerryDodge,来自文档:"The # character permits a numeric character or a plus or minus sign in this position, but doesn't require it."。如果小数点前至少需要一个数字字符,可以在小数点前添加一个0

标签: delphi


【解决方案1】:

每次修改编辑控件的内容时都会触发OnChange 事件。虽然这是过滤掉无效字符的合适位置,但它不是验证数值的合适位置。无法预测用户打算输入什么数字,无论是5505005,000,其中的每一个都可能会或可能不会被接受。

解决方案 1:在填写完这两个编辑控件并且用户尝试进入下一步(保存、继续、加载、启动等)后执行此检查。

解决方案 2:您可以在这些控件旁边显示“无效条目”标签,而不是显示消息框,同时保持相同的逻辑。这样用户就不会面对大量的消息框。

解决方案 3:使用 OnExit 事件而不是 OnChange。请注意,这不会完全解决您的问题,而是将其最小化。当焦点离开控件时触发此事件。

解决方案 4 与解决方案 2 类似,使用 OnChangeOnExit 来控制用户可能接下来按下的按钮的 Enabled 属性。

解决方案 5 与解决方案 4 类似,使用操作并更改该特定操作的 Enabled 属性。然后,用户可能按下的任何按钮都不能被点击。


附带说明,当您过滤掉无效字符时,忽略这些字符并且一开始就不要让它们进入控件而不是弹出消息会更优雅一些。您可以改用OnKeyPress 事件或TMaskEdit 来完成此操作。

【讨论】:

  • 考虑使用OnExit而不是OnChange进行验证。
  • @MarcusAdams 我要提到这一点,但是 OP 会面临类似的问题,因为有两个字段正在相互验证。
  • 我的意思是想象这些字段已经设置为0 .. 100 并且用户尝试将其更改为200 .. 500。如果使用OnExit,也会出现同样的问题,除非在最小值之前更改了最大值。
  • 我在 OnChange 和 OnExit 都进行了验证。让我看看 OnKeyPress 事件。我想你的意思是我使用 OnKeyPress 而不是 OnChange 或 OnExit 事件?
  • @user1505202 假设用户希望输入5000。他们按下5 并得到一个错误窗口。然后他们按0 和另一个错误窗口。然后再两次,再出现 2 个错误窗口。您真的希望您的用户看到这么多错误窗口吗?我建议解决方案 2,您可以在其中保留当前的验证,除了不显示对话框,只需在这些字段旁边放一个小标签。如果有效,则隐藏标签。如果无效,请出示标签。就这么简单。
【解决方案2】:

作为 OnExit 或 OnChange 的替代方法,我可以建议一种面向对象的模式方法:

  1. 定义模型对象。 TMyBusinessModelObject = class ....
  2. 在 View 对象中定义一个函数,将数据复制到模型对象。
  3. 在模型对象中进行验证。
  4. 如果有意义,请在需要时启动验证,即模式对话框关闭时。如果您需要在屏幕上显示颜色代码,例如图像或状态指示器,请使用 OnExit 事件。
  5. 编写单元测试,以便了解模型对象、视图模型或控制器对象是否正常工作以及业务逻辑是否正常工作。

其次,甚至比您编写代码以阻止无效字符的TMaskEditTEdit 更好,JVCL 中有专门为数字输入设计的控件,包括允许您直接在控件级别输入约束的控件.

Delphi 是一个面向组件的 RAD 工具,当您像使用它一样使用它时,并且从一开始就避免使用代码隐藏形式(Big Ball of Mud),您就不会遇到巨大的混乱稍后清理。 (一个相当可悲的事实是,标准的 Delphi 实践是做最简单的事情,并构建一个巨大的泥球,没有 OOP。)

【讨论】:

  • 我敢肯定,您所说的不仅仅是智慧。但是,不幸的是,我太初学者了,无法掌握您建议的细节。 Jerry Dodge 的一个建议对我有用,现在我不得不把它留在那里。也许有一天我会学会更好地编程。无论如何,谢谢,我感谢您的意见。
  • 只是为了澄清那些不知道的人,“RAD”代表“快速应用程序开发”。这也是一个 rad 首字母缩略词。
  • 或者更进一步,将特定的业务规则封装在 DLL 中,例如 MyDatabase.dllMyCommon.dllMyUsers.dllMyEncryption.dll 等等 - 这就是我的m 在做自己的过程中,一次从零开始构建大型软件基础架构。这是一件大事,需要大量的知识 - 但是当您了解这些概念的大部分时,一切都会变得更加容易。
  • 嗯,很明显,我有很多东西要向你们学习。感谢您的帮助!
猜你喜欢
  • 2023-03-14
  • 1970-01-01
  • 2017-04-24
  • 1970-01-01
  • 2018-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多