Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Как создать поле ввода, которое принимает только числа в Delphi: решение проблемы с NumbersOnly свойством и фильтрацией ввода

Delphi , Компоненты и Классы , TEdit

 

Проблема с NumbersOnly свойством TEdit

Многие разработчики Delphi сталкиваются с проблемой, когда стандартное свойство NumbersOnly компонента TEdit не работает должным образом, особенно при использовании определенных виджетсетов, таких как Cocoa, GTK2 или GTK3. Как видно из обсуждения на форуме, пользователь atlatl столкнулся именно с этой проблемой, когда мог вводить любые символы, несмотря на установленное свойство NumbersOnly.

Решения проблемы

1. Использование обработчика OnKeyPress

Простейшее решение - создать обработчик события OnKeyPress для вашего TEdit:

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: char);
begin
  // Разрешаем цифры (коды 48-57), Backspace (код 8) и Delete (код 46)
  if not ((Ord(Key) in [48..57]) or (Ord(Key) = 8) or (Ord(Key) = 46)) then
    Key := #0;
end;

Этот код позволяет вводить только цифры и использовать клавиши Backspace и Delete. Однако у этого метода есть недостаток - он не защищает от вставки текста через буфер обмена.

2. Улучшенная версия с поддержкой отрицательных чисел и десятичных разделителей

Если вам нужно разрешить ввод отрицательных чисел и десятичных разделителей:

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: char);
begin
  if not (Ord(Key) in [48..57]) and     // цифры
     not (Ord(Key) = 8) and             // Backspace
     not (Ord(Key) = 46) and            // Delete
     not ((Ord(Key) = 45) and (TEdit(Sender).SelStart = 0)) and // минус только в начале
     not ((Ord(Key) = 44) and (Pos(',', TEdit(Sender).Text) = 0)) then // запятая только одна
    Key := #0;
end;

3. Проверка через таймер (универсальное решение)

Для более надежной проверки, включая защиту от вставки текста, можно использовать таймер:

function IsValidNumber(const AText: string; AllowFloat, AllowNegative: Boolean): Boolean;
var
  Dummy: Double;
  I: Integer;
begin
  Result := TryStrToFloat(AText, Dummy);

  if not Result and AllowNegative then
    Result := TryStrToFloat(Copy(AText, 2, MaxInt), Dummy) and (AText[1] = '-');

  if not Result and not AllowFloat then
    Result := TryStrToInt(AText, I);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if not IsValidNumber(Edit1.Text, True, True) then
    Edit1.Text := '';
end;

Установите интервал таймера на 100-200 мс для быстрой реакции.

4. Использование TryStrToInt вместо исключений

Как отметил пользователь wp, лучше использовать TryStrToInt вместо StrToInt с обработкой исключений:

function IsAnInteger(const AText: string): Boolean;
var
  Dummy: Integer;
begin
  Result := TryStrToInt(AText, Dummy);
end;

5. Альтернативные компоненты

Если вам нужно более надежное решение, рассмотрите использование специализированных компонентов:

  1. TSpinEdit - встроенный компонент для ввода чисел
  2. TATEdit из пакета TATSynEdit (как упомянул AlexTP) с OptInputNumberOnly
  3. TJvValidateEdit из библиотеки JVCL

Пример полной реализации

Вот пример полной реализации компонента, наследующего от TEdit, с поддержкой только числового ввода:

type
  TNumericEdit = class(TEdit)
  private
    FAllowFloat: Boolean;
    FAllowNegative: Boolean;
    procedure SetAllowFloat(const Value: Boolean);
    procedure SetAllowNegative(const Value: Boolean);
    procedure CheckText;
  protected
    procedure KeyPress(var Key: Char); override;
    procedure DoEnter; override;
    procedure Change; override;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property AllowFloat: Boolean read FAllowFloat write SetAllowFloat default False;
    property AllowNegative: Boolean read FAllowNegative write SetAllowNegative default False;
  end;

constructor TNumericEdit.Create(AOwner: TComponent);
begin
  inherited;
  FAllowFloat := False;
  FAllowNegative := False;
end;

procedure TNumericEdit.KeyPress(var Key: Char);
begin
  inherited;

  if not (Ord(Key) in [48..57]) and     // цифры
     not (Ord(Key) = 8) and             // Backspace
     not (Ord(Key) = 46) and            // Delete
     not ((Ord(Key) = 45) and FAllowNegative and (SelStart = 0)) and // минус
     not ((Ord(Key) in [44, 46]) and FAllowFloat and 
          (Pos(FormatSettings.DecimalSeparator, Text) = 0)) then // десятичный разделитель
    Key := #0;
end;

procedure TNumericEdit.CheckText;
var
  D: Double;
  I: Integer;
  IsValid: Boolean;
begin
  if Text = '' then Exit;

  if FAllowFloat then
    IsValid := TryStrToFloat(Text, D)
  else
    IsValid := TryStrToInt(Text, I);

  if not IsValid and FAllowNegative then
    if Text[1] = '-' then
      if FAllowFloat then
        IsValid := TryStrToFloat(Copy(Text, 2, MaxInt), D)
      else
        IsValid := TryStrToInt(Copy(Text, 2, MaxInt), I);

  if not IsValid then
    Text := '';
end;

procedure TNumericEdit.DoEnter;
begin
  inherited;
  CheckText;
end;

procedure TNumericEdit.Change;
begin
  inherited;
  CheckText;
end;

procedure TNumericEdit.SetAllowFloat(const Value: Boolean);
begin
  FAllowFloat := Value;
  CheckText;
end;

procedure TNumericEdit.SetAllowNegative(const Value: Boolean);
begin
  FAllowNegative := Value;
  CheckText;
end;

Заключение

Хотя свойство NumbersOnly в TEdit не всегда работает корректно на всех платформах, существует несколько способов реализовать числовой ввод в Delphi. Выбор метода зависит от ваших требований:

  1. Для простых случаев достаточно обработчика OnKeyPress
  2. Для более надежной проверки используйте таймер или наследуйте свой компонент
  3. Для профессиональных решений рассмотрите специализированные компоненты

Представленные решения работают на всех виджетсетах, включая проблемные Cocoa, GTK2 и GTK3, и обеспечивают надежный ввод только числовых значений.

Создано по материалам из источника по ссылке.

В контексте описывается проблема неработающего свойства NumbersOnly компонента TEdit в Delphi и предлагаются различные решения для реализации числового ввода, включая обработчики событий, таймеры, проверку текста и использование альтернативных компоненто


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: TEdit ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-04-23 04:24:51/0.0036690235137939/0