Delphi TNumberBox - 如何仅允许正整数值?
我使用的是 Delphi 10.2,但以下内容也可能适用于其他 Delphi 版本。 我正在为 Android 进行开发,但我也在调试 Windows 版本。
TNumberBox 具有 ValueType 属性,可以将其设置为 Integer
。由此产生的行为是不一致的。一方面,用户可以输入带有十进制数字的数字(例如5.5
),TNumberBox 会处理它并从其Value
属性返回四舍五入的值。因此,ValueType=Integer
以某种方式工作。另一方面,为什么 TNumberBox 显示带有小数点的键盘(并且不能使用 KeypadType
属性将其修剪为仅整数位)并允许在 TNumberBox 中输入小数点/分隔符与 ValueType=Integer
?所以,这是德尔福的悲哀。
我尝试使用以下代码进行解决方法,过滤掉在 TNumberBox.OnTyping 事件上执行的小数分隔符和其他非数字字符:
function ReadDigits(AValue: string): string;
var i, Len, iHigh, iLow: Integer;
c: Char;
function CharIsDigit(AChar: Char): Boolean;
begin
Result:=False;
if (AChar in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) then begin
Result:=True;
end;
end;
begin
Result:='';
{iHigh:=High(AValue);
iLow:=Low(AValue);
for i:=iHigh downto iLow do begin
if (AValue[i] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) then begin
Result:=AValue[i]+Result;
end;
end;}
{//New Delphi uses 0-based strings
//https://stackoverflow.com/questions/19488010/how-to-work-with-0-based-strings-in-a-backwards-compatible-way-since-delphi-xe5
Len:=Length(AValue);
for i:=Len-1 downto 0 do begin
if (AValue[i] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) then begin
Result:=AValue[i]+Result;
end;
end; }
//It appears, that question about base is more complex and the answer may depend on the compiler directive
//https://stackoverflow.com/questions/21852034/delphi-loop-through-the-string
//It is not immediately clear, whether string-base differs among Windows/Android versions
for c in AValue do begin
if CharIsDigit(c) then
Result:=Result+c;
end;
end;
procedure TTabbedwithNavigationForm.edIntegerHoursTyping(Sender: TObject);
begin
edIntegerHours.Text:=ReadDigits(edIntegerHours.Text);
end;
但结果行为至少在两种方面非常奇怪:
- 而
88< /code> ir 正确转换为
88
,888
转换为100
! 问题已更新这一点已解决 - TNumberBox 默认情况下有Max=100
,这只是默认值的效果。 - 可以尝试单击 TNumberBox 并用鼠标选择(突出显示/标记)数字(或其一部分),甚至这样的选择也会改变数字,显然,选择操作会触发 OnTyping 事件等。
可以有很多调试更进一步,但我决定停下来咨询一下其他人。我是否采取了正确的路径来配置 TNumberBox 以仅输入整数值?以及如何做到这一点?
额外更新 我的用例要求只允许正整数值。我更新了问题标题并添加了此注释以进行澄清。
I am using Delphi 10.2, but the following may apply to other Delphi editions as well.
I am developing for Android, but I am debugging the Windows release as well.
TNumberBox has property ValueType and one can set it to Integer
. The resulting behavior is inconsistent. From the one side the user can enter the number with decimal digits (e.g. 5.5
) and the TNumberBox takes care of it and it returns rounded value from its Value
property. So, the ValueType=Integer
works in some manner. On the other hand, why TNumberBox displays the Keypad with decimal points (and one can not trim this with KeypadType
property down to the integer digits only) and allows to enter decimal point/separator at all in the TNumberBox with ValueType=Integer
? So, this is sad thing about Delphi.
I have tried to make workaround with the following code, that filters out decimal separators and other non-digit characters, that execute on TNumberBox.OnTyping event:
function ReadDigits(AValue: string): string;
var i, Len, iHigh, iLow: Integer;
c: Char;
function CharIsDigit(AChar: Char): Boolean;
begin
Result:=False;
if (AChar in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) then begin
Result:=True;
end;
end;
begin
Result:='';
{iHigh:=High(AValue);
iLow:=Low(AValue);
for i:=iHigh downto iLow do begin
if (AValue[i] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) then begin
Result:=AValue[i]+Result;
end;
end;}
{//New Delphi uses 0-based strings
//https://stackoverflow.com/questions/19488010/how-to-work-with-0-based-strings-in-a-backwards-compatible-way-since-delphi-xe5
Len:=Length(AValue);
for i:=Len-1 downto 0 do begin
if (AValue[i] in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) then begin
Result:=AValue[i]+Result;
end;
end; }
//It appears, that question about base is more complex and the answer may depend on the compiler directive
//https://stackoverflow.com/questions/21852034/delphi-loop-through-the-string
//It is not immediately clear, whether string-base differs among Windows/Android versions
for c in AValue do begin
if CharIsDigit(c) then
Result:=Result+c;
end;
end;
procedure TTabbedwithNavigationForm.edIntegerHoursTyping(Sender: TObject);
begin
edIntegerHours.Text:=ReadDigits(edIntegerHours.Text);
end;
But the resulting behavior is very strange in at least 2 ways:
- While
88
ir converted correctly to88
, the888
is converted to100
! QUESTION UPDATED This point is solved - TNumberBox hasMax=100
by default and this was just the effect of the default value. - One can try to click in the TNumberBox and select (highlight/mark) the number (or part of it) with the mouse and even such selection changes the number, obviously, the selection operation triggers OnTyping event etc.
There can be lot of debugging further, but I decided to stop for a moment and consult with other. Am I taking the right path to configure TNumberBox for entering integer values only? And how to do this?
ADDITIONAL UPDATE My use case requires that only positive integer values are allowed. I updated question title and added this note for clarification.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
FilterChar 不是 TNumberBox 的已发布属性,但我认为您仍然可以通过代码设置它,这将允许您进一步限制输入的字符。
FilterChar is not a published property of TNumberBox, but I think you can still set it by code, which will allow you to restrict the inputted characters even more.