Перейти к содержанию
Fire Monkey от А до Я
  • 0

Очистить очеред нажатий на кнопку


gresaggr

Вопрос

Как избежать повторных нажатий/ закликиваний на кнопку?

Имеется следующий код:

procedure Tfm.ButtonPrevCardClick(Sender: TObject);
begin
  ButtonPrevCard.Enabled := false;
  Application.ProcessMessages;


 // здесь код по смене карты + пауза в 2 секунды

  ButtonPrevCard.Enabled := true;
  Application.ProcessMessages;
end;

Под Windows повторных нажатий/закликиваний при этом не происходит.

А под Андроид, если пользователь быстро подряд нажал несколько раз, то сработает также несколько раз.
 

Ссылка на комментарий

Рекомендуемые сообщения

  • 0

1. Критическая секция, мониторы, семофоры-светофоры - пробовал? - один из способов

2. Button.Enabled := False/True - самый простой способ

3. Глобальный флаг

 

P.S. Лучше отдели логику от интерфейса

Изменено пользователем egorea1999
Ссылка на комментарий
  • 0

везде, где вижу

 Application.ProcessMessages;

сразу вспоминаю бессмертное:

- у вас на стройке несчастные случаи были?

- нет

- будут...

 

хорошим решением будет сделать Button.Enabled := False и после этого запустить поток, который

1. делает все что там вам нужно

2. при окончании работы разблокирует кнопку

3** Можно также запустить антизависательный таймер, который, если от потока не приходит вестей N секунд, прибивает поток и разблокирует кнопку

Ссылка на комментарий
  • 0
27 минут назад, krapotkin сказал:

 

3** Можно также запустить антизависательный таймер, который, если от потока не приходит вестей N секунд, прибивает поток и разблокирует кнопку

Никогда не предлагайте таких вещей, надо делать всегда все правильно и без костылей, чтобы даже таких мыслей не возникало. Имхо.

Ссылка на комментарий
  • 0

Кому не сложно, попробуйте у себя проверить:

Button1.Enabled:=false;
 

 Memo1.Lines.Add ('тест'); // или что-то другое сделать, чтобы можно было отследить

пауза

Button1.Enabled:=true;

 

И несколько раз быстро нажмите на кнопку. Запуск не под Windows, а под Android.

Как у вас все это отобразится?

Может быть чего-то недопонимаю, но неужели на такую элементарную штуку, как нажатие на кнопку нужно "...после этого запустить поток, который 1. делает все что там вам нужно 2. при окончании работы разблокирует кнопку" и т.п.?


 

P.S. В моем случае логика была отделена от интерфейса:  // здесь код по смене карты + пауза в 2 секунды: в этом месте вызывается процедура. Или в нее также рекомендуете убрать enable кнопки?
 

Изменено пользователем gresaggr
Ссылка на комментарий
  • 0

никто вообще не знает, что такое "код по смене карты" и зачем ждать 2 секунды в обработчике кнопки

поток предложен потому что предполагается, что это какая-то времязатратная операция

вообще же рассуждаем логически

натыкав по кнопке, мы получаем несколько событий в очереди сообщений

ваш обработчик первого клика УЖЕ вызван из метода ProcessMessages, внутри него вызов опять ProcessMessages, который опять вызовет обработчик если повезет, то второго клика и так по кругу....

поэтому не надо делать обработку сообщений в обработчике сообщений...

Ссылка на комментарий
  • 0

и да, я не понял, что должно быть по-вашему в коде

procedure TForm1.b1Click(Sender: TObject);
begin
  b1.Enabled := false;
  m1.Lines.Add('test');
  Sleep(1000);
  b1.Enabled := true;
end;

?

натыкал 5 раз. получил через пять секунд пять строчек test. потому что просто не успевает отображаться каждая очередная строка, т.к. вызывается вновь обработчик

что не так ?

Ссылка на комментарий
  • 0
4 минуты назад, krapotkin сказал:

и да, я не понял, что должно быть по-вашему в коде


procedure TForm1.b1Click(Sender: TObject);
begin
  b1.Enabled := false;
  m1.Lines.Add('test');
  Sleep(1000);
  b1.Enabled := true;
end;

?

натыкал 5 раз. получил через пять секунд пять строчек test. потому что просто не успевает отображаться каждая очередная строка, т.к. вызывается вновь обработчик

что не так ?

Я хочу чтобы было так:

К примеру клик. Enable = false. Началась пауза. В  момент паузы еще успели кликнуть три раза. Пауза завершилась. Enable=true.  Вот эти три клика в момент паузы не должны считаться.
 

Ссылка на комментарий
  • 0

вооот

поэтому надо, чтобы из очереди сообщений они ушли...

у вас логическая ошибка на слове "пауза". не стоит в обработчике делать паузу вообще. запустили таймер или поток, и вышли.

все остальные клики не сработают, пока кнопка задизаблена, но события обработаются штатно

потом таймер или поток вернет ее в enabled и все будет работать без всяких пауз

вот то, что вам нужно (uses system.treading)

procedure TForm1.b1Click(Sender: TObject);
begin
  b1.Enabled := false;
  m1.Lines.Add('test');

  TTask.Run(
    procedure
    begin
      sleep(2000);
      TThread.Synchronize(nil,
        procedure
        begin
          b1.Enabled := True;
        end);
    end);
end;

 

Ссылка на комментарий
  • 0
10 минут назад, krapotkin сказал:

procedure TForm1.b1Click(Sender: TObject); begin b1.Enabled := false; m1.Lines.Add('test'); TTask.Run( procedure begin sleep(2000); TThread.Synchronize(nil, procedure begin b1.Enabled := True; end); end); end;

Огромное вам спасибо! Теперь все работает корректно!
 

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...