如何在Delphi中验证文本框只包含数字?

9

这可能是一个非常简单的问题,但我从未接触过Delphi。

我有一个编辑框,可以输入字符。但在某些特殊情况下,我必须验证编辑框中的字符是否仅为数字。

我们该怎么做呢?

注意:用户可以输入任何字符,但在验证时,我必须验证上述条件。


4
为什么你不想阻止用户输入无效数据?许多开发人员认为,用户在输入字段中遇到无效数据时会被困住,这被视为“用户陷阱”,是糟糕的用户界面设计。请说明原因。 - Warren P
@Warren,请您澄清一下为什么要阻止用户在源处输入值,从而剥夺他们看到按键产生字符出现在屏幕上的反馈? - David Heffernan
1
不允许用户输入无效值到控件中,并不意味着不给予他反馈。你仍然可以弹出一些消息,比如“您输入了错误的值等等...”,就像在Windows登录时Capslock打开时那样。 - Stefan Glienke
@Warrent,是你提出“不响应按键”,这确实会令人困惑。 - David Heffernan
@Stefan - 这正是我所希望的。为什么用户要填写无效数据(例如字符到数字框中),并得到错误消息指出他们做错了什么。在我看来这样可以节省时间。 - user532231
显示剩余5条评论
4个回答

12

我不知道你打算使用什么事件来触发验证,但是可以像这样进行验证:

if TryStrToInt(Edit1.Text, Value) then
  DoSomethingWithTheNumber(Value)
else
  HandleNotANumberError(Edit1.Text);

2
在调用DoSomethingWithTheNumber之前,不应该加上“else”吗? - awmross
@awmross 很好的观点。在我脑海中,错误处理程序引发了异常,但这太强烈和假设了。 - David Heffernan
哦,谢谢!我之前是将编辑框文本转换为字符并逐个比较是否存在于集合或[0..9]中。基于此尝试了一下,但这种方法看起来更简洁。 - PawanS
1
@GAPS 如果你想限制答案只针对软件的12岁版本,那么在提问时应该明确说明。 - David Heffernan

8
我不明白为什么你想允许用户输入一个字符,但之后又不允许它通过验证。如果你真的需要阻止输入,那么最好使用控件来完成,而不是自己动手去解决。如果你使用的delphi版本比较旧,可以尝试使用JVCL组件库中的TJvValidateEdit,在所有版本的delphi中都可用。然而,在普通的近期delphi版本(2009及以后),已经内置了几种可能的解决方案,包括TMaskEdit和TSpinEdit。如果你只需要编写一个验证方法,那么考虑使用正则表达式或手写的验证函数,并将该代码与控件分开保留。
// Taking OP question obsessively literally, this 
// function doesn't allow negative sign, decimals, or anything
// but digits
function IsValidEntry(s:String):Boolean;
var
  n:Integer;
begin
  result := true;
  for n := 1 to Length(s) do begin
    if (s[n] < '0') or (s[n] > '9') then
    begin
       result := false;
       exit;
    end;
  end;
end;

我的想法完全一样,但我无法理解这段代码,David的代码只用了一行:TryStrToInt() - Johan
3
他说:“但在某些特殊情况下,我必须验证编辑框中的字符只是数字。”因此,他需要仅在特定情况下验证,而不是始终如此。顺便说一下,请将NumbersOnly属性添加到Delphi最近版本的编辑控件的内置解决方案列表中。将NumbersOnly属性设置为True将使编辑控件拒绝任何非数字字符。 - vcldeveloper
1
在我看来,NumbersOnly 不是一个有效的选项,通过 WinAPI(ES_NUMBER)设置也不行,因为即使这样,您仍然可以粘贴无效的文本。 - Stefan Glienke
哦,@vcldeveloper 发现了有趣的东西!听起来有问题吗? - Warren P
@Stefan,我无法在使用Delphi 2010的Windows 7中重现您提到的问题。将其NumbersOnly属性设置为True的编辑控件不接受任何字母字符粘贴进去。 - vcldeveloper
我刚在Windows XP上进行了测试,根据http://msdn.microsoft.com/en-us/library/bb775464.aspx,您可以粘贴非数字字符到编辑器中。尽管似乎他们在Vista及更高版本上做了一些改变(还请参阅msdn文章中的评论)。 - Stefan Glienke

4
我知道你说“用户可以输入任何字符,但在验证时”,但我想提供一个替代方案,因为允许用户输入值,然后在1分钟后向用户抱怨似乎非常愚蠢;这很不好。
我会禁止输入除数字以外的任何内容。 如果您有整数,那就特别容易:
填写编辑框的OnKeyPress事件。
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char) ;
begin
  if not(Key IN ['0'..'9', #8, #9, #13, #27, #127]) then key:= #0;
end;

这将删除任何不是数字的字符。

如果允许负数,您需要额外检查是否在输入符号“-”之前。

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char) ;
var
  Edit1Text: string;
begin
  if (Key = '-') and Pos('-',Edit1.Text) = 0 then begin
    Edit1.Text:= '-' + Edit1.Text;  //Force the '-' to be in the front.
  end
  else if (Key = '-') and Pos('-',Edit1.Text) <> 0 then begin  //else flip the sign
    Edit1Text:= Edit1.Text;
    Edit1.Text:= StringReplace(Edit1Text, '-', '',[]);
  end;
  if not(Key IN ['0'..'9', #8, #9, #13, #27, #127]) then key:= #0;
end;

由于用户也可以将数据粘贴到编辑框中,因此您仍需要在编辑文本更改时检查数据。
由于在ONKeyPress事件中进行这种操作会变得相当麻烦,因此我使用自定义编辑组件来进行此类检查,并防止用户将“口误”输入输入编辑框。

个人认为永远不应发出错误消息,您应始终努力不允许用户首先输入无效数据。


你可能想将该集合更改为 ['0'..'9', #8, #9, #13, #27, #127, '-']。特别是退格和删除对于输入很方便。 ;) (对于浮点数,您可能还想包括DecimalSeparator。) - NGLN
1
@Johan:小心。并不是所有的错误都来自用户,如果你不告诉用户出了什么问题,这会导致他们感到沮丧。 - Mason Wheeler
虚拟踩了一下。问题陈述为“用户可以输入任何字符,但在验证时我必须验证以上一个”。尽管如此,您的答案仍值得考虑。 - Kromster
4
由于可以通过多种方式将数据输入到编辑框中(例如粘贴文本),因此您仍然需要在退出/更改时验证文本。 - PetriW
个人观点是,我不认为应该发出错误消息,你应该始终努力不允许用户一开始就输入无效数据。但这只能做到一定程度上,你必须让用户发现为什么他们的输入不被接受。 - David Heffernan
显示剩余7条评论

4
但在某些特殊情况下,我需要验证编辑框字符只能是数字。
您需要两个编辑控件。一个用于仅数字值,另一个用于允许所有值。启用或禁用符合条件的控件。如果这两个控件具有良好的标题(和可能的提示,为什么控件已启用或禁用),则用户知道他必须输入什么以及为什么。
我不喜欢阻止用户。一个场景:
1. 我输入“abc123”; 2. 离开编辑控件时,我收到错误消息“仅允许数字”; 3. 我意识到我忘记了满足特殊条件; 4. 我想做一些事情来达到特殊条件; 5. 但我不能,因为我总是收到错误消息“仅允许数字”; 6. 所以我必须将值更正为“123”; 7. 做到达到特殊条件的事情; 8. 再次输入我的旧“abc123”值。
对于简单的数据输入表单,我会采取以下步骤:允许错误输入,但将每个具有无效输入的编辑控件的字体颜色切换为红色(当不允许空值时,红色字体颜色不足够)。如果用户尝试发布数据,则会给出一个错误消息,通知用户所有无效的输入字段并中止发布。

是的!!我也是这样做的。但是有一件事情我想提一下关于那个条件。那个条件仅仅基于一个复选框的值,没有更多的东西。 - PawanS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接