• 0
osvirt

Компилятор игнорирует программное изменение свойств компонентов

Вопросы

Доброе время суток.

Проблема в следующем:

Создаю пустое FM-приложение.

Кидаю кнопку и любой прямоугольный компонент(проверял на TLayout, на котором лежал TRectangle, и на TPanel).

У "прямоугольника" Visible установлено в False.

На событие кнопки OnClick вешаю обработчик:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Panel1.Visible:=true;  //TLayout.Visible:=true;
  sleep(2000);
  Panel1.Visible:=false; //TLayout.Visible:=false;
end;

Запускаю...

Происходит следующее:

По клику выполняется sleep, и только после этого быстро-быстро видимость включается/отключается. При этом, пока действует sleep, кнопка остаётся нажатой.

Получается, что часть функций выполняются как-будто по OnMouseDown, а часть по OnMouseUp.

 

В VCL приложении всё в порядке: видимость включается, программа ждёт 2 секунды, видимость отключается.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 ответов на этот вопрос

  • 0

Слипом вы подвешиваете главный поток, поэтому кнопка остаётся нажатой. Почему не происходит прорисовка, я точно сказать не могу, но скорее всего связано с подвешенным главным потоком.

 

Чтобы ваш код заработал, можно, например, использовать "Application.ProcessMessages" (кнопка будет нажата):

procedure TForm1.Button1Click(Sender: TObject);
begin
  Panel1.Visible := True;
  Application.ProcessMessages;

  Sleep(3000);

  Panel1.Visible := False;
  Application.ProcessMessages;
end;

Или воспользоваться потоками (кнопка будет в обычном состоянии):

procedure TForm1.Button1Click(Sender: TObject);
begin

  TThread.CreateAnonymousThread(
  procedure
  begin

    TThread.Synchronize(nil,
    procedure
    begin
      Panel1.Visible := True;
    end);

    TThread.Sleep(3000);

    TThread.Synchronize(nil,
    procedure
    begin
      Panel1.Visible := False;
    end);

  end
  ).Start;

end;

Можно написать вот так (без синхронизации тоже работает, это у меня уже в привычку вошло, работу с визуальными компонентами в синхронизацию запихивать): Используйте вариант описанный выше.

procedure TForm1.Button1Click(Sender: TObject);

begin

  TThread.CreateAnonymousThread(

  procedure

  begin

    Panel1.Visible := True;

    TThread.Sleep(3000);

    Panel1.Visible := False;

  end

  ).Start;

 

end;

 

 

Возможно, есть более лучшее решение...

Изменено пользователем Andrey Yefimov
Убрал плохой вариант...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

 

 

Слипом вы подвешиваете главный поток, поэтому кнопка остаётся нажатой. Почему не происходит прорисовка, я точно сказать не могу, но скорее всего связано с подвешенным главным потоком.

На сколько я помню, События OnClick происходят после нажатия и последующего отпускания кнопки мыши на одном и том же контроле... Но никак не после нажатия, не взирая на то, что событие "Click" по сути ещё не произошло. Странно, в-общем.

 

 

 

Сделал так - покрасивше вроде. Спасибо!

Можно написать вот так (без синхронизации тоже работает, это у меня уже в привычку вошло, работу с визуальными компонентами в синхронизацию запихивать):

procedure TForm1.Button1Click(Sender: TObject);
begin

  TThread.CreateAnonymousThread(
  procedure
  begin

    Panel1.Visible := True;

    TThread.Sleep(3000);

    Panel1.Visible := False;

  end
  ).Start;

end;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

работаем с gui не из основного потока ? ну-ну... продолжайте в таком духе...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

работаем с gui не из основного потока ? ну-ну... продолжайте в таком духе...

 

Ну, в данном конкретном случае (исходя из описанной задачи) можно и без синхронизации, а вообще конечно все действия с GUI очень желательно проводить через синхронизацию (т.е. в основном потоке). Я как бы рассчитывал, что человек сам заглянет в справку и разберёт код. Возможно, вы правы и не нужно было выкладывать такой вариант...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

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

 

Почитал про "Application.ProcessMessages" и воспользовался им - всё встало на свои места.

 

Еще раз спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

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

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу