Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Предотвратить повторное нажатие кнопки (без потоков)

11K
10 сентября 2012 года
proc
32 / / 23.07.2006
Здравствуйте.
Есть кнопка, по щелчку на ней выполняется цикл и увеличивается значение счетчика в TEdit. Если пользователь нажимает кнопку второй раз, до того как завершилось выполнение первого вызова функции, то, соответственно, счетчик увеличится еще на единицу. Нужно сделать, чтобы пока не завершится вызов первой функции - вторая не вызывалась. Возможно это сделать без использования потоков?

P.S.
Первое же, что пришло в голову - использование глобальной переменной. Выставляем 1 при первом запуске и 0 после его завершения. Пока стоит 1 - второй вызов функции прерываем. Но получается, что второй вызов функции помещается в очередь и стартует уже после того, как завершен первый, т.е. значение переменной во время второго вызова равно 0 и нажатие все равно обрабатывается.
40K
11 сентября 2012 года
D129
228 / / 18.04.2012
Возможно, что просто выставить свойтсво frmProp.btnGetBrutto.Enabled := False; - недостаточно.
Надо сразу после этого прокачать очередь сообщений - чтобы они обработались.
В винформах это Application.DoEvents()
или Refresh() этому контролу....
что-то аналогичное должно быть и в дельфи.
40K
10 сентября 2012 года
D129
228 / / 18.04.2012
Чисто логически - все правильно.

Сделайте замедлитель. после нажатия - деактивируйте конопку, и запустите таймер, на полсекунды - чтобы он ее разморозил. Но это мне, как пользователю, было бы неприятно. А если я вот хочу быстро-быстро нащелкать счетчик?
:-)
11K
10 сентября 2012 года
proc
32 / / 23.07.2006
Ха! Вот это да! Мне бы в голову не пришло )))

Т.е. как я понимаю в начале процедуры сделать кнопку неактивной, а в конце процедуры вставить строку "Timer1.Enabled := True;" и уже в процедуре самого таймера "Button1.Enabled := True; Timer1.Enabled := False"? Блин... Я аплодирую стоя! Конечно над внедрением такого алгоритма еще стоит подумать, но вот сама идея - гениальна ))).

Думаю все-таки это не совсем то, что я имел ввиду. Вопрос остается открытым.
40K
10 сентября 2012 года
D129
228 / / 18.04.2012
Хотите очередь сообщений чистить? А разве делать кнопку неактивной - это не то же самое?
1
10 сентября 2012 года
kot_
7.3K / / 20.01.2000
Цитата: proc
Ха! Вот это да! Мне бы в голову не пришло )))

Т.е. как я понимаю в начале процедуры сделать кнопку неактивной, а в конце процедуры вставить строку "Timer1.Enabled := True;" и уже в процедуре самого таймера "Button1.Enabled := True; Timer1.Enabled := False"? Блин... Я аплодирую стоя! Конечно над внедрением такого алгоритма еще стоит подумать, но вот сама идея - гениальна ))).

Думаю все-таки это не совсем то, что я имел ввиду. Вопрос остается открытым.


если самое простое решение - то делать кнопку неактивной в начале процедуры, и активировать в конце. И просто и эффективно

11K
11 сентября 2012 года
proc
32 / / 23.07.2006
Вот в том-то все и дело, что когда я ставлю Enabled кнопки в False в начале процедуры и True в конце - все равно, если продолжать кликать мышкой по неактивной кнопке - процедура будет выполняться еще столько раз, сколько я кликнул. Почему? Не знаю. По всей логике вещей она не должна запускаться, после того, как кнопка стала неактивной, но почему-то запускается.
Если кнопку при первом запуске сделать неактивной - и в конце процедуры не выставлять Enabled в True, т.е. оставлять ее неактивной, то щелчки не обрабатываются. Вот поэтому я и делаю вывод, что в то время, пока кнопка неактивна и процедура выполняется, приложение все равно запоминает действия пользователя для кнопки, помещая их в очередь, и выполняет после того, как в конце процедуры мы вновь делаем кнопку активной.

Вот код, срабатывающий по нажатию кнопки:

procedure TfrmProp.btnGetBruttoClick(Sender: TObject);
var
Weight, StepWeight:double;

// Украшательства ради
//==================================================
// i:integer;
// Step:double;
// SWeight:double;
//==================================================
begin
frmProp.btnGetBrutto.Enabled := False;

// Защита от "дребезга"
if GetTickCount - frmProp.LastClick < CONTACT_NOISE_PROTECTION then exit
else frmProp.LastClick:= GetTickCount;

Weight:= Data.CurList.FieldByName('BRUTTO').AsFloat;
if ( Weight <> 0 ) and ( frmProp.AxesCount = 0 ) then begin
Weight:= 0;
Data.CurList.FieldByName('AXES_BRUTTO').AsString:= '';
end;

// Украшательства ради
//==================================================
// SWeight:= Weight;
//==================================================

StepWeight:= frmProp.GetWeight;
Weight:= Weight+StepWeight;
inc(frmProp.AxesCount);
Data.CurList.FieldByName('BRUTTO').AsFloat:= Weight;
Data.CurList.FieldByName('BRUTTO').AsString:= Data.CurList.FieldByName('BRUTTO').DisplayText;
if frmProp.AxesCount = 1 then
Data.CurList.FieldByName('AXES_BRUTTO').AsString:= Data.CurList.FieldByName('BRUTTO').AsString
else
Data.CurList.FieldByName('AXES_BRUTTO').AsString:= Data.CurList.FieldByName('AXES_BRUTTO').AsString + ', ' +
Format('%.1f', [StepWeight]);


// Украшательства ради
// Украшательство заключается в том, что
// Индикатор как бы постепенно "нарастает"
//==================================================
// Step:= (Weight-SWeight)/10;
// for i:= 1 to 10 do begin
// SWeight:= SWeight + Step;
// pnBrutto.Caption:= Format('%.1f', [SWeight]);
// Application.ProcessMessages;
// Sleep(30);
// end;
//==================================================

frmProp.pnBrutto.Caption:= Format('%.1f', [Data.CurList.FieldByName('BRUTTO').AsFloat]);
frmProp.pnAxes.Caption:= IntToStr(frmProp.AxesCount);
frmProp.LastWeight:= Weight;
frmProp.pnLastWeight.Caption:= Format('%.1f', [frmProp.LastWeight]);

frmProp.btnGetBrutto.Enabled := True;
end;

Вот код функции, которая вызывается внутри обработчика нажатия кнопки и имитирует какой-то процесс:

function TfrmProp.GetWeight: double;
begin
Result:= 12.4;
sleep(4000);
exit;
end;

Собственно все... Не могу понять - в чем дело. Скорее всего где-то что-то не доглядел.
11K
11 сентября 2012 года
proc
32 / / 23.07.2006
Спасибо за подсказку - решение найдено. Нужно было перед тем как выставлять Enabled в True, прочитать очередь сообщений и выполнить их. Программно - это всего лишь одна строчка кода, в конце процедуры:

frmProp.pnBrutto.Caption:= Format('%.1f', [Data.CurList.FieldByName('BRUTTO').AsFloat]);
frmProp.pnAxes.Caption:= IntToStr(frmProp.AxesCount);
frmProp.LastWeight:= Weight;
frmProp.pnLastWeight.Caption:= Format('%.1f', [frmProp.LastWeight]);
Application.ProcessMessages;
frmProp.btnGetBrutto.Enabled := True;
end;
7
11 сентября 2012 года
@pixo $oft
3.4K / / 20.09.2006
Ясен перец!Как я понял,весь код выполняется в одном потоке,т.е. пока он выполняется,идёт забивка сообщений в очередь.Разумеется,после его выполнения все сообщения сразу сваливаются на программу
Можно было поставить Application.ProcessMessages сразу после frmProp.btnGetBrutto.Enabled:=False,чтобы сообщения просто не генерировались(потому как кнопка будет заблокирована)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог