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

Поочередная загрузка изображений в TImage


Anasazi

Вопрос

Всем доброго времени суток. Возникла необходимость решить такую задачу: в таблице базы MySQL хранится список изображений и их URL. Необходимо получить этот список массивом. Затем загрузить изображения и поочередно с интервалом показать их в TImage.

Понимаю, что получить список изображений правильнее при помощи PHP скрипта, но в каком виде скрип должен вернуть данные, чтобы в Delphi получить из них массив не знаю.

Раньше для получения изображений использовал такую процедуру. Но вопрос, где хранить изображения перед демонстрацией их в TImage? Создавать несколько MemoryStream?

procedure LoadWebImage(url: string; image: TBitmap);
var
  idhttp : TNetHTTPClient;
  ms : TMemoryStream;
begin
 IdHTTP := TNetHTTPClient.Create(nil);
  ms := TMemoryStream.Create;
  try

    idhttp.Get(url, ms);
    ms.Position := 0;
    image.LoadFromStream(ms);

  finally
    ms.Free;
    idhttp.Free;
  end;
end;

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

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

  • 0
1 минуту назад, krapotkin сказал:

вместо TNetHttpClient вам нужен THttpClient

хотите - храните в TStream, хотите - в TBitmap

А как думаете, как лучше получить URL'ы? PHP пусть возвращает одной строкой и потом разбивать по разделителю?

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

не понял вопроса. но в принципе вообще все равно. 
исходим из того, что запросы - медленные. а программа быстрая.

как выгоднее так и делаем

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

Привет. Я не использовал такой путь. Организуйте свой проект.

procedure setLogo(ListView: TListView; code, url: string; id: Integer);
  var
   Cache: string;
   T: TThread;
 begin
   Cache := TPath.GetCachePath + '/AzerBoxPlus/Cache/';
   if not TFile.Exists(Cache + code + '.png') then
   begin
     T := TThread.CreateAnonymousThread(
     procedure
     var
       HTTP: TIdHTTP;
       MS: TMemoryStream;
     begin
       MS := TMemoryStream.Create;
       HTTP := TIdHTTP.Create(nil);
       try
         try
           HTTP.Get(url, MS);
           TThread.Synchronize(TThread.CurrentThread,
             procedure()
             begin
               ListView.Items[id].Bitmap.LoadFromStream(MS);
               MS.SaveToFile(Cache + code + '.png');
             end);
         except
           MS.Free;
         end;
       finally
         HTTP.Free;
		MS.Free;
		end;
     end);
     T.start;
   end else
   begin
     T := TThread.CreateAnonymousThread(
     procedure
     begin
       TThread.Synchronize(TThread.CurrentThread,
       procedure()
       begin
         ListView.Items[id].Bitmap.LoadFromFile(Cache + code + '.png');
       end);
     end);
     T.start;
   end;
 end;

setLogo(ListView, 'name', 'url', index);

 

 

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

T := TThread.CreateAnonymousThread( procedure begin TThread.Synchronize(TThread.CurrentThread, procedure() begin ListView.Items[id].Bitmap.LoadFromFile(Cache + code + '.png'); end); end); T.start;

с учетом Thread и Synchronize  тут по сути написано

ListView.Items[id].Bitmap.LoadFromFile(Cache + code + '.png');

 

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

Я не до конца понимаю. Вы задали мне вопрос?

@AliZairov

Эта конструкция:

end else
   begin
     T := TThread.CreateAnonymousThread(
     procedure
     begin
       TThread.Synchronize(TThread.CurrentThread,
       procedure()
       begin
         ListView.Items[id].Bitmap.LoadFromFile(Cache + code + '.png');
       end);
     end);
     T.start;
   end;
 end;

равнозначна одной строчке (ее можно заменить:):

ListView.Items[id].Bitmap.LoadFromFile(Cache + code + '.png');

 

TThread.Synchronize - означает "остановить текущий поток, и запустить указанную процедуру в главном (GUI) потоке".

 

 

Еще один момент 

 

 

 except
    MS.Free;  << эта строка не нужна, т.к. код в finally будет выполнен при срабатывании исключения.
  end;
finally
  HTTP.Free;
  MS.Free;
end;

Если вам нужно загасить исключение - то можно сделать пустой блок, без кода. 

try 

except 

end;

Изменено пользователем ENERGY
Ссылка на комментарий
  • 0
  • Модераторы
В 19.05.2017 в 16:10, Anasazi сказал:

А как думаете, как лучше получить URL'ы? PHP пусть возвращает одной строкой и потом разбивать по разделителю?

Собрать массив на пхп и сделать json_encode, на стороне Делфи распарсить json и дальше грузить ссылки

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

равнозначна одной строчке (ее можно заменить:):

ListView.Items[id].Bitmap.LoadFromFile(Cache + code + '.png');

Это верно только в том случае, если мы заранее знаем, что процедура SetLogo будет всегда вызываться только из основного потока. Если что-то менять - я бы код

    T := TThread.CreateAnonymousThread(
     procedure
     begin
       TThread.Synchronize(TThread.CurrentThread,
       procedure()
       begin
         ListView.Items[id].Bitmap.LoadFromFile(Cache + code + '.png');
       end);
     end);
     T.start;

заменил бы следующим:

TThread.ForceQueue(TThread.CurrentThread,
  procedure()
  begin
    ListView.Items[id].Bitmap.LoadFromFile(Cache + code + '.png');
  end);

 

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

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

Если так рассуждать, тогда нужно каждое обращение к элементу интерфейса облачать в ForceQueue конструкцию. "А вдруг с другого потока обратятся"?

Имхо "не следует множить сущности без необходимости".

Изменено пользователем ENERGY
Ссылка на комментарий
  • 0
В 19.05.2017 в 14:05, AliZairov сказал:

Привет. Я не использовал такой путь. Организуйте свой проект.


procedure setLogo(ListView: TListView; code, url: string; id: Integer);

...

 @ENERGY, я говорил об этой процедуре, а ее можно вызвать откуда угодно. Ведь задача и состоит в том, чтобы в теле этой процедуры синхронизировать обращение к элементам GUI с главным потоком. Ведь кто нам мешает к ней обратиться следующим образом:

T := TThread.CreateAnonymousThread(
  procedure
  begin
    setLogo(ListView, 'name', 'url', index);
  end);
T.start;

Кстати, в этом случае, внутри нее можно вообще избавиться от CreateAnonymousThread

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

@dnekrasov

Кстати у меня есть привычка, - методы, которые вызываются в отдельном потоке, к их именам обычно добавлю слово Thread. SetLogoThread. Очень рекомендую от путанницы.

Ну и если спорить дальше, то SetLogo не будет вызван в отдельном потоке, т.к. название метода уже намекает на GUI, а значит только главный поток, и анонимный поток внутри. :) 

 

 

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

@ENERGY

Хорошая привычка :). У меня тоже она есть, вот только слово - Operation :D.

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

Кстати, для меня это не спор, а обыкновенный обмен опытом, ведь спорить о том как и что лучше реализовать в большинстве случаев бесполезно, а вот знать как реализовать ту или иную задачу разными способами - просто необходимо.

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

Добрый вечер. Я использовал этот код для веб-телепроекта ABP. Были некоторые ошибки в коде он знает. Но, видя, полные необходимые процедуры. Мне нужно было, чтобы сделать эту систему из такой библиотеки. Picasso

5921c4936da2e_ScreenShot2017-05-21at20_47_09.png.d6c8093dced3feb177099152e5e98f55.png

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

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

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

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

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

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

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

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

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

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