Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Циклы, sleep(), ProgressBar


Автор: boobie 3.1.2013, 13:27
Добрый день!
Давно заметил такую штуку... 
Создаем одну кнопку и одну метку.
Вешаем вот такое событие на кнопку:
Код

procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
label1.Caption:='';
for I := 0 to 10 do
  begin
    label1.Caption:=inttostr(i);
    sleep(1000);
  end;
end;

Как я представлял себе работу цикла: i:=0, выводим i, ждем одну секунду; i:=1, выводим, ждем еще одну секунду... и так до 10.
Но нет. После нажатия на кнопку программа замирает на 10 секунд (это ожидаемо... ведь у нас sleep() и отсутствие многопоточности)...
А уже потом показывается "10". Почему не происходит перерисовка label1?

Если немного "усложнить" и добавить ProgressBar, например, так:
Код

procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
label1.Caption:='Форматирование диска C:\';
for I := 0 to 100 do
  begin
    progressbar1.Position:=progressbar1.Position+1;
    sleep(60);
  end;
progressbar1.Position:=0;
label1.Caption:='';
end;

"Гусеница" бежит нормально,  а надпись 'Форматирование диска C:\' даже не появляется.
Если убрать строчку
Код

label1.Caption:='';

то надпись 'Форматирование диска C:\' появится после того, как пробежит "гусеница".
Почему? 
Пользуюсь Delphi XE3.

Автор: Illusion Dolphin 3.1.2013, 14:16
Цитата

Почему не происходит перерисовка label1?

Потому что
Цитата

программа замирает на 10 секунд


Цитата

"Гусеница" бежит нормально,

Потому что она обновляется между sleep'ами (SendMessage, а не PostMessage). 

Есть глупая функция delay, если на неё заменить Sleep то выглядить всё будет красиво:
Код

procedure Delay (Seconds: Real);
var
Later: TDateTime;
begin
Later:= Now + (Seconds / (24.0 * 60.0 * 60.0));
While Now < Later do Application.ProcessMessages;
end; 


Пользоваться ею в проектах - крайне не рекомендую, а просто посмотреть - пожалуйста.
Application.ProcessMessages обрабатывает все сообщения, которые пришли в программу. В данном случае надо как минимум WM_PAINT и ещё что-нибудь наверное чтобы прорисовать Label. 

Автор: northener 3.1.2013, 14:26
Цитата(Illusion Dolphin @  3.1.2013,  14:16 Найти цитируемый пост)
В данном случае надо как минимум WM_PAINT и ещё что-нибудь наверное чтобы прорисовать Label.

Достаточно TLabel.Refresh или TLabel.Repaint

Автор: boobie 3.1.2013, 14:28
Спасибо!
TLabel.Repaint - все как надо...

А почему без него не обойтись?

Автор: Illusion Dolphin 3.1.2013, 14:52
Цитата

А почему без него не обойтись?

Без него можно обойтись через потоки или Application.ProcessMessages. Просто Repaint принудительно перерисовывает контрол.

Автор: northener 4.1.2013, 01:46
Цитата(boobie @  3.1.2013,  14:28 Найти цитируемый пост)
Спасибо!
TLabel.Repaint - все как надо...

А почему без него не обойтись?

Вам бы стоит почитать что-нибудь про Windows.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)