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

FMX асинхронное управление интерфейсом в процедуре до её завершения.


Светлана

Вопрос

Ну всё в принципе как всегда, либо я барашка, либо лыжи не едут)

А всё просто - я хочу, чтобы пока данные с сервера загружались по клику кнопки, пользователю элементарно был отклик в виде крутящейся какой нибудь фигни и он видел, что процесс идёт и что прога не зависла и никуда лишний раз не тыкал.

Пока что для тестов сделала элементарно кнопку Update (speedbutton с image), данные элементарно грузятся и отображаются в GridPanel, а поверх него, чтоб пользователь и не смог куда либо тыкнуть, замостила панелькой с Image, вращаемой по таймеру (всё это дело наверху Visible:=false). И когда клацаем по кнопке Update, то панельку сверху грида делаю отображаемой и запускаю таймер, потом этот же обработчик/процедура грузит данные, а по окончанию останавливаем таймер и скрываем полупрозрачну, еще кстати, панельку. Аля вот так:

procedure TForm1.SB_DataUpdateClick(Sender: TObject);
	begin
      //отображаем лого загрузки
      P_showLoad.Visible := true;
      Timer_load_rotate.Enabled := true; //с запуском таймера
		
      GetDeD_List(DE_set.Date); //процедура загрузки и отображения чего нам надо, которая весьма долго выполняется

	  //и скрывае лого загрузки
      Timer_load_rotate.Enabled := false; //уже в обратном порядке
      P_showLoad.Visible := false;
    end;

иии... ни черта не происходит как я хочу(

Это лого вообще в итоге не отображается, а если убрать его скрытие, то оно у нас отобразится уже только тогда, когда всё загрузится. Логика мне стала подсказывать, что следовало его как то отобразить выполнив в параллельном асинхронном потоке аля так:

procedure TForm1.SB_DataUpdateClick(Sender: TObject);
	begin
      TThread.Queue(TThread.Current,  //TThread.Queue TThread.Synchronize ForceQueue
        procedure()
        begin
           P_showLoad.Visible := true;
           Timer_load_rotate.Enabled := true;
        end);
		
      GetDeD_List(DE_set.Date); //процедура загрузки и отображения чего нам надо, которая весьма долго выполняется
    end;

И опять оно отображается только после того, как всё загрузится и проработает вся процедура. И уже чего только не пробовала и Synchronize и ForceQueue; и через TTask.Run и |task := TTask.Create(procedure () ... и т.д.| ничего не подходит, вот хоть убейся это всё дело будет отображаться только после полной отработки процедуры клика. Может я не в том направлении вообще рою и это как то по другому делается? Может я еще пока отлаживаю на Win32, а не всё на android, а там вот пара вариантов и норм на нём работают? Но чтот я никак не могу понять, что к чему... должно же быть как то просто, а я чтот никак не могу понять как(

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

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

  • 0
1 час назад, Светлана сказал:

Логика мне стала подсказывать, что следовало его как то отобразить выполнив в параллельном асинхронном потоке

Ну правильно Вам логика подсказала, вот только в отдельном потоке надо запускать ВСЁ. Аля так:

TThread.CreateAnonymousThread(procedure
  begin
    TThread.ForceQueue(TThread.Current,  
      procedure
      begin
        P_showLoad.Visible := true;
        Timer_load_rotate.Enabled := true;
      end);

    GetDeD_List(DE_set.Date);

    TThread.ForceQueue(TThread.Current,  
      procedure
      begin
        P_showLoad.Visible := False;
        Timer_load_rotate.Enabled := False;
      end);
  end);

P.S.

Не проверял, но логика, я думаю, ясна

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

TThread.CreateAnonymousThread(procedure begin ... end);

Либо не работает вообще, либо пробую дописать .Start и выбивает ошибку.

Логика ясна, начала перебирать варианты, но... меня терзают какие то смутные сомнения, что может ничего не получиться, потому что реакция на вложения еще хуже, чем ожидалось. Хотелось бы всё таки более ясный мануал за потоки к FMX, почитать, чтоб точно понять как они работают и на основе этого сделать как лучше, а не методом тыка костыли создавать.

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

Либо не работает вообще, либо пробую дописать .Start и выбивает ошибку

Да, извините - забыл, конечно надо TThread.CreateAnonymousThread(procedure begin ... end).Start, ведь он создаётся как Suspended

14 минут назад, Светлана сказал:

но... меня терзают какие то смутные сомнения, что может ничего не получиться,

Я их довольно часто использовал (пока не перешёл на работу с TTask), всегда всё отрабатывало нормально.

15 минут назад, Светлана сказал:

Хотелось бы всё таки более ясный мануал

Пройдитесь по форумам или блогам, почитайте хелп :)

 

А Вообще - в Вашем случае Image и таймер никогда не будет отрабатывать, пока GetDeD_List запускается в главном потоке

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

А если я ловлю ошибку иногда "Exception class DOMException with message 'Microsoft MSXML is not installed'" - это значит, что то типа потоку не доступна та или иная lib для выполнения?

Ссылка на комментарий
  • 0
3 часа назад, Светлана сказал:

Логика ясна, начала перебирать варианты, но... меня терзают какие то смутные сомнения, что может ничего не получиться, потому что реакция на вложения еще хуже, чем ожидалось. Хотелось бы всё таки более ясный мануал за потоки к FMX, почитать, чтоб точно понять как они работают и на основе этого сделать как лучше, а не методом тыка костыли создавать.

"Курите" мануалы! Купите книжку "Delphi High Performance" в конце концов, там хорошо все разжевано!

На YouTube есть множество роликов о том как правильно делать...

Все видимое выполняйте в главном потоке, все вычисления, запросы, обработку выносите в потоки и будет Вам счастье Анатолий Светлана!

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

Светлана, вот как делаю я:

 

procedure TMainClient.ОбновитьДанныеВПотоке
begin
  TThread.CreateAnonymousThread(procedure ()
    begin
      TThread.Synchronize (nil, //Из потока обращаемся к контролам только через главгый поток
      procedure ()
      begin
        Показываем котролы запускаем мультик
      end);
      
      Выполняем обработку данных без использования визуальных элементов 

      TThread.Synchronize(nil, 
      procedure ()
      begin
        Выполняем остановку мультика скрываем контролы
      end);
  end).Start;
end;

 

Ссылка на комментарий
  • 0
13 часов назад, Светлана сказал:

А если я ловлю ошибку иногда "Exception class DOMException with message 'Microsoft MSXML is not installed'" - это значит, что то типа потоку не доступна та или иная lib для выполнения?

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

Ссылка на комментарий
  • 0
В 16.10.2019 в 02:29, Светлана сказал:

А если я ловлю ошибку иногда "Exception class DOMException with message 'Microsoft MSXML is not installed'" - это значит, что то типа потоку не доступна та или иная lib для выполнения?

Еще, причем, если будете запускать не только на Windows, сразу выберете кросплатформенного поставщика (DOM Vendor) ADOM XML v4

Тогда не надо будет вызывать CoInitialize, который и работает только для Windows

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

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

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

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

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

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

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

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

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

  • Похожий контент

    • Автор Delpher-X
      Итак, как добавить в приложение проверку наличия соединения с Интернетом? Я всегда пользовался кодом: 
      var NetControl : DWORD; begin NetControl := INTERNET_CONNECTION_MODEM + INTERNET_CONNECTION_LAN + INTERNET_CONNECTION_PROXY; Result := InternetGetConnectedState(@NetControl, 0); end; Однако здесь он явно не подходит, так как предназначен для Windows, а меня интересует Android. Я пробовал использовать компонент IdIPWatch, но он все время верещал о том что Интернета нет, несмотря на то что смартфон был вполне подключен к сети. 
    • Автор Delpher-X
      Вопрос: как спрятать главную форму приложения в FMX? В VCL это делается просто - Project>View Source>вписываешь в открывшемся окне Application.ShowMainForm := False, однако в FMX такой фокус не прокатывает, там просто свойства такого нет - ShowMainForm. Как же быть? 
    • Автор Delpher-X
      Пытаюсь программно добавить в своем проекте компонент IdFTP: 
      FTPBot : TIdFTP; FTPBot := TIdFTP.Create(); FTPBot.Name := 'FTPGhost'; FTPBot.Passive := True; FTPBot.Host := ''; FTPBot.Username := ''; FTPBot.Password := ''; Код компилируется нормально. 
      Однако, когда я пытаюсь обратиться к свойству TransferType полученного объекта: 
      FTPBot.TransferType.ftBinary; Программа при компиляции вылетает с ошибкой, утверждает что нельзя так писать. В чем дело? 
    • Автор Simons Cat
      У меня среда программирования rad studio Delphi 10.4.2. Собственно ищу совета как отправить и получить ответ на запрос USSD.
      Нашел в интернете единственный пример более или менее который похож на правду.
      Привел его к виду нормальному виду, но не хватает знаний как передать функцию CallBack.
      procedure TForm7.Button6Click(Sender: TObject); var Temp:Jstring; ResponceCallBack: JTelephonyManager_UssdResponseCallback; handler: JHandler; begin     TM :=TJTelephonyManager.Create;   handler := TJHandler.Create;   ResponceCallBack := TJTelephonyManager_UssdResponseCallback.Wrap(   TAndroidHelper.Context.getSystemService(TJContext.JavaClass.TELEPHONY_SERVICE));    TM.sendUssdRequest(StringToJString('*100#'), ResponceCallBack,handler);   end;  
      На java делается вот так. Не знаю как этот код переделать в delphi.
      TelephonyManager =  telephonyManager(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);     Handler handler = new Handler();     TelephonyManager.UssdResponseCallback callback = new TelephonyManager.UssdResponseCallback() {         @Override         public void onReceiveUssdResponse(TelephonyManager telephonyManager, String request, CharSequence response) {             super.onReceiveUssdResponse(telephonyManager, request, response);             Log.e("ussd",response.toString());           }           @Override         public void onReceiveUssdResponseFailed(TelephonyManager telephonyManager, String request, int failureCode) {             super.onReceiveUssdResponseFailed(telephonyManager, request, failureCode);             Log.e("ussd","failed with code " + Integer.toString(failureCode));         }     };       try {            Log.e("ussd","trying to send ussd request");            telephonyManager.sendUssdRequest("*123#",                     callback,                     handler);         }catch (Exception e){                 String msg= e.getMessage();             Log.e("DEBUG",e.toString());             e.printStackTrace();         }  
    • Автор Aigazy
      Добрый день всем!

      Сейчас пишу десктопное приложение на Delphi FMX.
      На тач скринах не визуализируется эффект нажатия на кнопки (TButton, TSpeedButton, TCornerButton и тд.) и на другие компоненты, которые должны иметь эффект нажатия. Обработчик события onClick при этом работает стабильно, а вот эффект нажатия нет. Событие onMouseDown работает через раз.
      На стандартных приложениях FMX эффект нажатия на кнопки проявляется через раз или зависит от силы нажатия на тач экран или от нажатия подушкой пальца.
      В других стандартных приложениях Windows (проводник, калькулятор, блокнот и т.д.) все работает, эффект нажатия правильно визуализируется.
      Я хотел использовать FMX стили в своем проекте, но без визуального эффекта нажатия, портится общая картина всего приложения и не понятно нажалась ли кнопка.
      Кто-нибудь сталкивался с данной проблемой? Мне посоветовали обратиться в Embarcadero's Quality Portal, но у меня увы нет аккаунта, с которого я смог бы опубликовать данный баг (если это баг, конечно же :)).
      Буду очень признателен за помощь)
      Я снял на видео данный баг. Заранее прошу прощения за качество съемки.
      https://drive.google.com/file/d/1UQnZ-K_F_l3bOfp81Zl9WNym2t7RbxC0/view?usp=sharing
      https://drive.google.com/file/d/16KN5HXXrgPseL54iMzPk3umJvjaqDisU/view?usp=sharing
    • Автор Delpher-X
      Я обратил внимание, что если в VCL цвет формы, а также некоторых других компонентов можно менять, то в FMX это сделать нельзя - доступен только дефолтно-серый, во всяком случае, при компиляции под Android. Есть ли какие-то способы это поправить? 
    • Автор Delpher-X
      У меня есть следующий код, который передает данные из потока в объект типа TStrings: 
      var F : TMemoryStream; S : TStrings; begin F := TMemoryStream.Create; S := TStringList.Create; F.LoadFromFile('C:/File.jpg'); S.LoadFromStream(F); Из TMemoryStream в TStrings все передается нормально. Однако - как обратно? Как снова преобразовать объект TString в поток данных, дабы снова можно было бы сохранить его в полноценный файл? 
    • Автор slav_z
      Все разработчики при работе с FMX рано или поздно сталкиваются с одной и той же проблемой: необходимо исключить "случайное" срабатывание нажатий элементов внутри скроллбокса во время его скроллинга. Идут годы, а решения так и нет. Давайте попробуем это исправить. Поехали!
      Запускаем IDE, создаем новый проект, кидаем на форму TVertScrollBox и на него чего-нибудь побольше... запускаем на мобильном устройстве, пытаемся скроллировать,

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

      Все. Переносим код в базовую форму, делаем его более гибким, убираем все те костыли, которые мы уже успели сделать ранее...
      Удачи!
      https://github.com/slav-libx/scroll-click.git
    • Автор uakmal
      Здравствуйте!
      Создаю медиаплеер для Android TV. 
      Запускаю плеер, нажимаю на условную кнопку, которая делает следующее: 
      MediaPlayer1.FileName:='/storage/emulated/0/download/1.mp4'; После нажатия вылетает окошко с надписью:
      java.lang.java.lang.illegalargumentexception после закрытия окошки нажимаю на play, но ничего не происходит.
      Подскажите, пожалуйста как исправить это?
    • Автор Delpher-X
      Итак, я пробовал использовать компоненты AppTethering для передачи данных между VCL-приложением работающим под Windows и мобильным FMX-приложением и потерпел неудачу, так как выяснилось что потоки данных данные компоненты на деле не передают. И у меня возник вопрос: а нет ли каких других компонентов в современной Embarcadero Studio, которые бы позволяли передавать как строковые данные, так и файлы между приложениями? Особенно меня интересуют все же файлы. 
  • Последние посетители   0 пользователей онлайн

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

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