rustam_d Опубликовано 4 августа, 2015 Поделиться Опубликовано 4 августа, 2015 DelphiXE8, Android. Задача: загрузить в ImageList иконки 32х32 из базы данных. Проблема: Не получается Transparent никак. Как обычно перелопатил кучу форумов и ссылок и человеко-часов (эх vcl отнял бы 1 минуту...), и удалось написать тестовое приложение. Однако прозрачность никак не работает...иконка, что в тесте в поставке делфи идет, цвет розовый. В дизайне все ок, а вот самому... Закомментировал то что не помогает всеравно, но хотел показать что пробовал ). Проверяю результат по иконке что на кнопке через action. Иконка норм отображается, но с ней и розовый цвет... procedure TForm1.Button4Click(Sender: TObject); var Layer: TLayer; c: TCustomSourceItem; b: TCustomBitmapItem; d: TCustomDestinationItem; begin d := ImageList1.Destination.Add; Layer := ImageList1.Destination[d.Index].Layers.Add; Layer.SourceRect.Rect := TRectF.Create(0, 0, 32, 32); c := ImageList1.Source.Add; Layer.Name := c.Name; //c.MultiResBitmap.TransparentColor := TAlphaColorRec.Fuchsia; b := c.MultiResBitmap.Add; b.Bitmap.SetSize(32,32); b.Bitmap.LoadFromFile('C:\Delphi\Images\GlyFX\glyFX\Icons\Aero\BMP\32x32\eject_blue_32_h.bmp'); //b.Bitmap.Clear(TAlphaColorRec.Fuchsia); Action2.ImageIndex := 3; end; Цитата Ссылка на комментарий
0 AngryOwl Опубликовано 4 августа, 2015 Поделиться Опубликовано 4 августа, 2015 А что Вам мешает сделать сразу PNG-иконку с нужной прозрачностью, и подгружать ее, а не мучать TransparentColor и т.п.? Цитата Ссылка на комментарий
0 FIL Опубликовано 4 августа, 2015 Поделиться Опубликовано 4 августа, 2015 Прозрачность почему-то применяется только если загружать картинку через редактор MultiResBitmap. Причем прозрачный цвет должен быть выбран до загрузки. Похоже на очередной косяк разработчиков. Цитата Ссылка на комментарий
0 rustam_d Опубликовано 4 августа, 2015 Автор Поделиться Опубликовано 4 августа, 2015 Друзья спасибо вам за оперативные ответы. Начал юзать png вместо bmp и кажется все ок. Сори за беспокойство, но может кому пригодиться. Цитата Ссылка на комментарий
0 RoschinSpb Опубликовано 4 сентября, 2015 Поделиться Опубликовано 4 сентября, 2015 Причем прозрачный цвет должен быть выбран до загрузки. Похоже на очередной косяк разработчиков. Не похоже нет. См. демонстрационное видео https://www.youtube.com/watch?v=3voFs62PYl0&feature=youtu.be&t=260 Если у вас сохранилось имя файла, то можно заново загрузить все изображения с новыми параметрами и в числе прочего с новым цветом прозрачности. Хотя параметры изображения действительно применяются только в момент загрузки. Потому, что это все-таки не фотошоп и исходник картинки не хранится в FMX. То, что попадает в FMX это часто результат обработки с потерей данных. Т.е. если исходное изображение 128x128 сначала сделать 16х16, а потом 32х32, то качество количество деталей будет как у 16х16. Поэтому цвет и размеры применяются только один раз в момент загрузки, что позволяет минимизировать потери. В FMX-файле данные хранятся только в png-формате (во всяком случае на текущий момент). Редактор в IDE использует функцию TCustomBitmapItem.CreateBitmap. MultiresBitmap имеет свойства Width, Height, TransparentColor, SizeKind. Каждый элемент этой коллекции MultiresBitmap имеет свойство FileName, Scale. Функция CreateBitmap на основе этих данных создает TBitmap. Если она вернула не nil, то вы можете присвоить эту картинку элементу коллекции TMultiresBitmap. Кактотак мы перегружаем все изображения. MultiresBitmap.BeginUpdate; try for I := 0 to TMultiresBitmap.Count - 1 do begin FmxBitmapSource := MultiresBitmap[I].CreateBitmap; try if Assigned(FmxBitmapSource) then begin MultiresBitmap[I].Bitmap.Assign(FmxBitmapSource); end else begin MultiresBitmap[I].Bitmap.SetSize(0, 0); MultiresBitmap[I].FileName := ''; end; finally FreeAndNil(FmxBitmapSource); end; end; finally MultiresBitmap.EndUpdate; Если у вас TransparentColor не clNone, то просто попиксельно заменяется указанный цвет на полностью прозрачный. Если TransparentColor = clDefault, то используется цвет нижней левой точки. Исходники CreateBitmap доступны, так что можете взять за основу, и сделать что-то подобное, если данные грузятся не из файла. А что касается добавления картинок в TImageList, то можно посмотреть статью http://community.embarcadero.com/blogs/entry/timagelistxe8ru и демку, которая поставляется в составе Delphi, или взять её отсюда http://sourceforge.net/p/radstudiodemos/code/HEAD/tree/trunk/Object%20Pascal/FireMonkey%20Desktop/ImageList FIL и Andrey Efimov 2 Цитата Ссылка на комментарий
0 rustam_d Опубликовано 4 сентября, 2015 Автор Поделиться Опубликовано 4 сентября, 2015 Причем прозрачный цвет должен быть выбран до загрузки. Похоже на очередной косяк разработчиков. Не похоже нет. Сергей, я был бы очень признателен по сабжу, т.е. не могли бы вы как профи поправить мой код? Убрать все лишнее, дестинейшн может быть и т.п., и оставить только нужное и правильное? Цитата Ссылка на комментарий
0 RoschinSpb Опубликовано 4 сентября, 2015 Поделиться Опубликовано 4 сентября, 2015 Сергей, я был бы очень признателен по сабжу, т.е. не могли бы вы как профи поправить мой код? Убрать все лишнее, дестинейшн может быть и т.п., и оставить только нужное и правильное? Попробую. Выкладывайте на всеобщее обозрение здесь, или в комментариях к статье. Andrey Efimov 1 Цитата Ссылка на комментарий
0 rustam_d Опубликовано 4 сентября, 2015 Автор Поделиться Опубликовано 4 сентября, 2015 Сергей, я был бы очень признателен по сабжу, т.е. не могли бы вы как профи поправить мой код? Убрать все лишнее, дестинейшн может быть и т.п., и оставить только нужное и правильное? Попробую. Выкладывайте на всеобщее обозрение здесь, или в комментариях к статье. так это и есть тема сообщения... Цитата Ссылка на комментарий
0 RoschinSpb Опубликовано 4 сентября, 2015 Поделиться Опубликовано 4 сентября, 2015 Загрузка картинки будет выглядеть примерно так. procedure TForm11.Button2Click(Sender: TObject); const SourceName = 'Картинка'; procedure LoadPicture(const Source: TCustomSourceItem; const Scale: Single; const FileName: string); var BitmapItem: TCustomBitmapItem; TmpBitmap: TBitmap; begin BitmapItem := Source.MultiResBitmap.ItemByScale(Scale, True, True); if BitmapItem = nil then begin BitmapItem := Source.MultiResBitmap.Add; BitmapItem.Scale := Scale; end; BitmapItem.FileName := FileName; TmpBitmap := BitmapItem.CreateBitmap; try if TmpBitmap <> nil then BitmapItem.Bitmap.Assign(TmpBitmap); finally TmpBitmap.Free; end; end; var NewSource: TCustomSourceItem; NewDestination: TCustomDestinationItem; NewLayer: TLayer; begin if ImageList1.Source.IndexOf(SourceName) = -1 then begin NewSource := ImageList1.Source.Add; NewSource.Name := SourceName; NewSource.MultiResBitmap.TransparentColor := TColorRec.Fuchsia; NewSource.MultiResBitmap.SizeKind := TSizeKind.Custom; NewSource.MultiResBitmap.Width := 16; NewSource.MultiResBitmap.Height := 16; LoadPicture(NewSource, 1, 'D:\Мои веселые картинки\Icons\16x16\alarm16.bmp'); LoadPicture(NewSource, 1.5, 'D:\Мои веселые картинки\Icons\24x24\alarm24.bmp'); NewDestination := ImageList1.Destination.Add; NewLayer := NewDestination.Layers.Add; NewLayer.SourceRect.Rect := TRectF.Create(TPoint.Zero, NewSource.MultiResBitmap.Width, NewSource.MultiResBitmap.Height); NewLayer.Name := SourceName; ControlAction1.ImageIndex := NewDestination.Index; end; end; Здесь как видно грузится деве картинки 16х16 и 24х24, при этом используются масштабы 1 и 1,5. После загрузки меняется свойство ImageIndex у действия ControlAction1. Загруженная картинка должна автоматом появится на всех кнопках, которые используют ControlAction1. rareMax и FIL 2 Цитата Ссылка на комментарий
0 FIL Опубликовано 4 сентября, 2015 Поделиться Опубликовано 4 сентября, 2015 (изменено) Одно выглядит странным: метод CreateBitmap объекта BitmapItem создает битмап в никуда лишь для того, чтобы программист потом вручную запихивал этот битмап обратно в BitmapItem) Да и св-во TransparentColor, которое учитывается лишь в одном методе, а в остальных случаях его изменение ничего не дает и лишь сбивает с толку... Может просто в CreateBitmap еще один параметр добавить? Изменено 4 сентября, 2015 пользователем FIL Цитата Ссылка на комментарий
0 rustam_d Опубликовано 4 сентября, 2015 Автор Поделиться Опубликовано 4 сентября, 2015 Может просто в CreateBitmap еще один параметр добавить? Фил я кстати тоже так подумал )))) Исправил в своем коде ТОЛЬКО ОДНУ строку и тогда транспарент заработал (чудеса FMX): b.Bitmap.Assign(b.CreateBitmap('C:\Delphi\Images\GlyFX\glyFX\Icons\Aero\BMP\32x32\eject_blue_32_h.bmp')); и даже удалил b.Bitmap.SetSize(32,32); Сергей, в любом случае вы помогли спасибо! Но мой код по мне куда проще и короче... Вообщем вот готовый простейший код procedure TForm1.Button1Click(Sender: TObject); var Layer: TLayer; c: TCustomSourceItem; b: TCustomBitmapItem; d: TCustomDestinationItem; begin d := ImageList1.Destination.Add; Layer := ImageList1.Destination[d.Index].Layers.Add; Layer.SourceRect.Rect := TRectF.Create(TPoint.Zero, 32, 32); c := ImageList1.Source.Add; Layer.Name := c.Name; c.MultiResBitmap.TransparentColor := TAlphaColorRec.Fuchsia; b := c.MultiResBitmap.Add; b.Bitmap.Assign(b.CreateBitmap('C:\Delphi\Images\GlyFX\glyFX\Icons\Aero\BMP\32x32\arrow_left_32_h.bmp')); Button2.ImageIndex := 0; end; Vitaldj 1 Цитата Ссылка на комментарий
0 rustam_d Опубликовано 4 сентября, 2015 Автор Поделиться Опубликовано 4 сентября, 2015 и еще может кому сгодиться, если в БД картинки не меняли, то логично, что их не зачем загружать. Для этого я просто сохраняю компонент ImageList в файл. Если есть лучше решения, то критика приветствуется! //сохраняем компонент ImageList в файл vStream := TFileStream.Create(TPath.GetDocumentsPath + '/imagelist',fmCreate); try vStream.WriteComponent(imgMain); finally vStream.Free; end; //загружаем файл в компонент ImageList vStream := TFileStream.Create(TPath.GetDocumentsPath + '/imagelist',fmOpenRead); try vStream.ReadComponent(imgMain); finally vStream.Free; end; Цитата Ссылка на комментарий
0 RoschinSpb Опубликовано 17 сентября, 2015 Поделиться Опубликовано 17 сентября, 2015 Может просто в CreateBitmap еще один параметр добавить? ... b.Bitmap.Assign(b.CreateBitmap('C:\Delphi\Images\GlyFX\glyFX\Icons\Aero\BMP\32x32\arrow_left_32_h.bmp')); ... vStream.WriteComponent(imgMain); 1. TransparentColor еще и хранится в fmx файле, и используется редактором IDE. На что недвусмысленно намекает документация по TransparentColor. CreateBitmap используется в редакторе изображений, она создает картинку по указанным параметрам, её можно и по своему усмотрению использовать, допустим вывести окошко и спросить "а действительно ли вы хотите добавить именно такую картинку". Почему используются свойства а не параметры функции? Ну потому, что заточена она для массовой загрузки нескольких однотипных изображений, скорее всего у них будут одинаковые параметры. P.S. Хотя в общем и целом принял к сведению возникшее затруднение, постараюсь как-нибудь упростить. 2. CreateBitmap создало картинку. Assign скопировало данные из этой картинки. А исходная картинка созданная CreateBitmap осталась в памяти и ссылки на неё нету. 3. В вашем примере сохраняется и загружается вся коллекция + разная служебная информация, что не добавляет скорости. Лучше бы сохранять и загружать сами битмапы из Source.MultiResBitmap с использованием LoadFromFile, SaveToFile (как в первом примере). Это будут файлы родные png и они будут грузится системными API функциями с максимальной скоростью. А CreateBitmap использовать только при первой загрузке чтобы cмасштабировать и сконвертировать в png. Хотя и так тоже можно, но я бы не стал. FIL 1 Цитата Ссылка на комментарий
0 rustam_d Опубликовано 17 сентября, 2015 Автор Поделиться Опубликовано 17 сентября, 2015 Может просто в CreateBitmap еще один параметр добавить? ... b.Bitmap.Assign(b.CreateBitmap('C:\Delphi\Images\GlyFX\glyFX\Icons\Aero\BMP\32x32\arrow_left_32_h.bmp')); ... vStream.WriteComponent(imgMain); 3. В вашем примере сохраняется и загружается вся коллекция + разная служебная информация, что не добавляет скорости. Лучше бы сохранять и загружать сами битмапы из Source.MultiResBitmap с использованием LoadFromFile, SaveToFile (как в первом примере). Это будут файлы родные png и они будут грузится системными API функциями с максимальной скоростью. А CreateBitmap использовать только при первой загрузке чтобы cмасштабировать и сконвертировать в png. Хотя и так тоже можно, но я бы не стал. что то не догнал...вот так просто взял и SaveToFile??? а для чего я тогна танцы с бубнами делаю с Destination ? Он что как то стороной проходит? Т.е. я беру и без всяких танцев с дестинанэйшн сразу Source.MultiResBitmap.LoadFromFile ? вы уверены? хм... А если вы про загрузку каждой картинки отдельно, то не вариант, мне же индексировать где то надо... да и если собьется индекс то уже и не те картинки на кнопках...причем на многих...неее, мне 300% уверенность нужна. Цитата Ссылка на комментарий
0 RoschinSpb Опубликовано 17 сентября, 2015 Поделиться Опубликовано 17 сентября, 2015 В 9/17/2015 в 18:08, rustam_d сказал: А если вы про загрузку каждой картинки отдельно, то не вариант, мне же индексировать где то надо...да и если собьется индекс то уже и не те картинки на кнопках...причем на многих...неее, мне 300% уверенность нужна. Да, я про загрузку каждой картинки в отдельности в Source. В 9/17/2015 в 05:02, RoschinSpb сказал: постараюсь как-нибудь упростить. В RAD Studio 10.1 Berlin (Version 24.0) появились методы TSourceCollection.AddOrSet и TCustomImageList.AddOrSet Как мне кажется смысл параметров довольно очевиден и не требует дополнительных пояснений. function AddOrSet(const SourceName: string; const Scales: array of Single; const FileNames: array of string; const TransparentColor: TColor = TColors.SysNone; const Width: Integer = 0; const Height: Integer = 0): TCustomSourceItem; Цитата Ссылка на комментарий
0 RoschinSpb Опубликовано 13 марта, 2017 Поделиться Опубликовано 13 марта, 2017 В 04.09.2015 в 19:00, RoschinSpb сказал: Загрузка картинки будет выглядеть примерно так. А вот вариант загрузки из этихвашихинтернетов из сети по заданному URL procedure TForm2.Button2Click(Sender: TObject); const SourceName = 'Картинка'; function LoadPicture(const SourceName: string; const Scale: Single; const URL: string): TCustomSourceItem; var HTTPClient: TNetHTTPClient; Stream: TMemoryStream; TmpBitmap: TBitmap; BitmapItem: TCustomBitmapItem; begin Result := nil; Stream := nil; TmpBitmap := nil; HTTPClient := TNetHTTPClient.Create(nil); try Stream := TMemoryStream.Create; HTTPClient.Get(URL, Stream); Stream.Position := 0; TmpBitmap := TBitmap.Create; TmpBitmap.LoadFromStream(Stream); if (TmpBitmap.Width > 0) and (TmpBitmap.Height > 0) then begin Result := ImageList1.Source.Add; Result.Name := SourceName; Result.MultiResBitmap.TransparentColor := TColorRec.Fuchsia; Result.MultiResBitmap.SizeKind := TSizeKind.Source; Result.MultiResBitmap.Width := Round(TmpBitmap.Width / Scale); Result.MultiResBitmap.Height := Round(TmpBitmap.Height / Scale); BitmapItem := Result.MultiResBitmap.ItemByScale(Scale, True, True); if BitmapItem = nil then begin BitmapItem := Result.MultiResBitmap.Add; BitmapItem.Scale := Scale; end; BitmapItem.Bitmap.Assign(TmpBitmap); end; finally HTTPClient.Free; TmpBitmap.Free; Stream.Free; end; end; var NewSource: TCustomSourceItem; NewDestination: TCustomDestinationItem; NewLayer: TLayer; begin if ImageList1.Source.IndexOf(SourceName) = -1 then begin NewSource := LoadPicture(SourceName, 1, 'http://voy.dk/wp-content/uploads/2010/06/Avril-lavigne-13thebestdamnthingmarkliddellshootnhy5_122_131lo-779x1024.jpg'); NewDestination := ImageList1.Destination.Add; NewLayer := NewDestination.Layers.Add; NewLayer.SourceRect.Rect := TRectF.Create(TPoint.Zero, NewSource.MultiResBitmap.Width, NewSource.MultiResBitmap.Height); NewLayer.Name := SourceName; Button1.ImageIndex := NewDestination.Index; end; end; Здесь приведен простейший вариант загрузки картинки как есть, т.е. она будет хранится в исходном размере. На телефоне может и не хватить места. Alex Bakulin 1 Цитата Ссылка на комментарий
0 ENERGY Опубликовано 29 марта, 2017 Поделиться Опубликовано 29 марта, 2017 (изменено) Не нашел я к сожалению в этой и других ветках простой код для добавления TBitmap в ImageList без лишних элементов. Все приходиться делать самому: Helper для ImageList type TImageListHelper = class helper for TImageList function Add(aBitmap: TBitmap): integer; end; function TImageListHelper.Add(aBitmap: TBitmap): integer; const SCALE = 1; var vSource: TCustomSourceItem; vBitmapItem: TCustomBitmapItem; vDest: TCustomDestinationItem; vLayer: TLayer; begin Result := -1; if (aBitmap.Width = 0) or (aBitmap.Height = 0) then exit; // add source bitmap vSource := Source.Add; vSource.MultiResBitmap.TransparentColor := TColorRec.Fuchsia; vSource.MultiResBitmap.SizeKind := TSizeKind.Source; vSource.MultiResBitmap.Width := Round(aBitmap.Width / SCALE); vSource.MultiResBitmap.Height := Round(aBitmap.Height / SCALE); vBitmapItem := vSource.MultiResBitmap.ItemByScale(SCALE, True, True); if vBitmapItem = nil then begin vBitmapItem := vSource.MultiResBitmap.Add; vBitmapItem.Scale := Scale; end; vBitmapItem.Bitmap.Assign(aBitmap); vDest := Destination.Add; vLayer := vDest.Layers.Add; vLayer.SourceRect.Rect := TRectF.Create(TPoint.Zero, vSource.MultiResBitmap.Width, vSource.MultiResBitmap.Height); vLayer.Name := vSource.Name; Result := vDest.Index; end; Хелпер позволяет добавлять свои методы, не наследуясь от класса. После этого можно обращаться к любому ImageList ImageList1.Add(MyBitmap); Изменено 30 марта, 2017 пользователем ENRGY Цитата Ссылка на комментарий
0 RoschinSpb Опубликовано 29 марта, 2017 Поделиться Опубликовано 29 марта, 2017 Использование Tag, как бы намекает Не стоит скрывать свойство TCustomSourceItem.Name от пользователя, пусть сам заботится об уникальности (не такая уж это большая проблема). Это свойство может быть использовано для предотвращения случайной повторной загрузки, допустим если есть картинка с указанным названием поднимать исключение. На случай, если нужно заменить имеющуюся картинку, можно добавить метод AddOrReplace. Успехов Цитата Ссылка на комментарий
0 ENERGY Опубликовано 29 марта, 2017 Поделиться Опубликовано 29 марта, 2017 (изменено) @RoschinSpb Цитата Использование Tag, как бы намекает Не стоит скрывать свойство TCustomSourceItem.Name от пользователя, пусть сам заботится об уникальности (не такая уж это большая проблема). Я честно говоря вообще не понимаю зачем туда ввели строковые имена и зачем они пользователю сдались. Индексов хватило бы с головой и быстрее бы работало - не нужно перебирать компаратором все эти массивы строк, и меньше бы памяти брало. Цитата Это свойство может быть использовано для предотвращения случайной повторной загрузки, допустим если есть картинка с указанным названием поднимать исключение. И это я тоже не понимаю, зачем нужно делать исключение на этот случай, по идее нужно было молча заменить картинку. У Delphi есть широкий выбор разнообразных списков, очередей, cтэков, массивов, деревьев и никогда в них не использовались имена. Для идентификации и унификации всегда использовалось число-индекс. У этого подхода гораздо больше плюсов, чем у строковых идентификаторов, почему решили отойти от этого стандарта, не понимаю... Изменено 29 марта, 2017 пользователем ENRGY Цитата Ссылка на комментарий
0 RoschinSpb Опубликовано 29 марта, 2017 Поделиться Опубликовано 29 марта, 2017 (изменено) 1 час назад, ENRGY сказал: по идее нужно было молча заменить картинку. Это смотря какая идея. В некоторых случаях уместно заменить, в некоторых это неуместно, или недопустимо. Например у Вас процедура инициализации (которая загружает сотню картинок) в процессе долгой разработки она перемещалась из OnShow в OnCreate потом в OnActivate где-то забыли удалить вызов и теперь эта процедура вызывается два раза. Допустим в приложении появилась вторая, третья, N+1 форма. Я не знаю отнаследовалась она, или просто скопипастилась, или Вы что-то добавили в Design-Time, так или иначе есть ненулевая вероятность получить неоднократное добавление одного и того же. Ситуация ошибочная и хорошо бы как-то об этом узнать, такая вот идея у меня была. В Вашем случае и не заменит и не предупредит об ошибке, т.е. потенциально имеем утечку ресурсов. Вы бы смогли догадаться, что изображено на этих картинках без доп. описания? Картинки конечно неважные, но в коде-то Вы их вообще не видите. В итоговой коллекции обращение идет всё равно по номеру, потому, что соображения совместимости важнее удобства, но во всяком случае есть возможность найти картинку по человекопонятному описанию например: ImageList1.Source.IndexOf('я'); ImageList1.Destination[0].Layers[0].Name; Надеюсь, я внес некоторое понимание. Кстати, при добавлении новой картинки по умолчанию у неё и так имеется уникальное имя вида "Item 0", "Item 1" и т. д. procedure TForm2.Button1Click(Sender: TObject); begin Button1.Text := ImageList1.Source.Add.Name; end; Изменено 29 марта, 2017 пользователем RoschinSpb Цитата Ссылка на комментарий
0 ENERGY Опубликовано 29 марта, 2017 Поделиться Опубликовано 29 марта, 2017 Цитата Вы бы смогли догадаться, что изображено на этих картинках без доп. описания? Картинки конечно неважные, но в коде-то Вы их вообще не видите. Имена можно было ввести, но опционально (description) - нужно юзеру, - добавил. Не нужно ну и не надо. В большинстве случаев описание не нужно. А те кому это нужно, обычно хранят это в своих структурах, в отдельном списке, где можно кроме описания, сохранить и др. параметры (путь к файлу, адрес итд). А сейчас это обязательный идентификатор, который, имхо, усложняет работу со списком.. Цитата Допустим в приложении появилась вторая, третья, N+1 форма. Я не знаю отнаследовалась она, или просто скопипастилась, или Вы что-то добавили в Design-Time, так или иначе есть ненулевая вероятность получить неоднократное добавление одного и того же Ну и что, это задача уже ложиться на программиста, причем здесь ImageList. Можно и не замещать, а просто добавить новую картинку, с тем же именем или игнорировать добавление. Как например в StringList сделано. Там по умолчанию выключено определение дубликатов и добавляется новая строка.. Представьте если бы StringList по умолчанию возбуждал исключение на дубликат строки, весело было бы.. Цитата Ссылка на комментарий
0 RoschinSpb Опубликовано 29 марта, 2017 Поделиться Опубликовано 29 марта, 2017 20 минут назад, ENRGY сказал: А сейчас это обязательный идентификатор, который, имхо, усложняет работу со списком.. Еще раз обращаю внимание: обязательный идентификатор инициализируется значением по умолчанию. Если не видите в нем смысла (это вовсе не значит что его нет), ни кто Вас не заставляет его использовать, по сути он и является опциональным. function TImageListHelper.Add(aBitmap: TBitmap; const AName: string = ''): integer; ... begin ... vSource := Self.Source.Add; if AName <> '' then vSource.Name := AName; Использование Tag мало того, что просто дурной тон, оно еще и лишнее и снижает базовую функциональность. Цитата это задача уже ложиться на программиста, причем здесь ImageList. С тем же успехом спрошу, а при чем здесь StringList, здесь больше уместна аналогия с TComponent.Name. Я Вам привел конкретные примеры зачем оно может использоваться (а может и не использоваться). Вы приводите гипотетические версии, что можно было бы сделать, конечно можно всё, можно даже заполнять список рандомными данными, но какой в этом практический смысл. И вообще мне странно, что Вы сначала жалуетесь, на излишнюю сложность и уже на следующей строке перекладываете на программиста куда более сложную задачу (формировать отдельные списки/структуры). В подавляющем большинстве случаев пользователь формирует коллекцию в DesignTime и не углубляется в дебри. Если же речь идет о динамической загрузке, это почти всегда что-то нестандартное, тут уже возможны всякие варианты (заменять, поднимать исключение, делать еще что-нибудь, не делать ни чего), но почти всегда важно застраховаться от повторной загрузки, или случайного перетирания одного изображения другим. И здесь могут помочь "человеческие" названия. В сложном приложении порядок загрузки может легко и непринужденно поменяться. Цитата Ссылка на комментарий
0 ENERGY Опубликовано 30 марта, 2017 Поделиться Опубликовано 30 марта, 2017 (изменено) @RoschinSpb Цитата Еще раз обращаю внимание: обязательный идентификатор инициализируется значением по умолчанию. по сути он и является опциональным. По сути он как раз является обязательным, потому что при добавлении картинки в список в runtime, нужно указывать уникальное имя, притом в двух местах. Было бы классно, если бы компонент сам создавал это имя (в Runtime), конечно было бы удобней если имя было представлено как необязательное поле Description. Цитата Использование Tag мало того, что просто дурной тон, оно еще и лишнее и снижает базовую функциональность. Ну без Tag пришлось бы вводит переменную-счетчик в класс текущей формы, что имхо только усложняет. А если форм несколько? Использовать глобальную переменную, тоже вариант, но это же костыль, такой же как и тэг. А если используются костыли, в таком простой случае, значит что-то не так.. Цитата И вообще мне странно, что Вы сначала жалуетесь, на излишнюю сложность и уже на следующей строке перекладываете на программиста куда более сложную задачу (формировать отдельные списки/структуры). Это имя нужно только компоненту TImageList. А юзеру чтобы отличать картинки в DesignTime в ImageList достаточно посмотреть на картинку. В остальных случаях - обращение через индексы. Туда не запишешь какое то серьезное описание. Как вы представляете это? Одни значения для обрабатываемой картинки (размер, имя, разрешение, и многое др.) храним и читаем со специально созданного для этого класса, а описание\имя читаем с ImageList? Это же не удобно и запутает. Плюс ImageList находится в юните GUI, где только GUI код, а вся логика работы обычно в отдельном классе ядра и к тому же код может быть мультипоточный. Плюс обычно если программисту нужно хранить описание картинки или имя, то оно должны быть writeable. А в ImageList оно readonly. Имхо это велосипед, явно усложняющий работу. Цитата а при чем здесь StringList, здесь больше уместна аналогия с TComponent.Name. Какая разница какой тип данных содержит список - строки, картинки - это просто data куски лежащие в памяти. Цитата Если же речь идет о динамической загрузке, это почти всегда что-то нестандартное, тут уже возможны всякие варианты Есть определенные стандарты написания похожих компонентов, втч. это и имена методов (Add, Remove, Insert etc), имхо разработчикам следовало бы держаться стандартов Delphi для списков, к которым за годы все привыкли. Изменено 30 марта, 2017 пользователем ENRGY Цитата Ссылка на комментарий
0 RoschinSpb Опубликовано 30 марта, 2017 Поделиться Опубликовано 30 марта, 2017 Цитата Было бы классно, если бы компонент сам создавал это имя (в Runtime) Я уже писал о том, что так оно и есть, и дважды приводил примеры которые это демонстрируют. Если бы это было не так, новый элемент просто не смог бы добавиться. procedure TForm2.Button1Click(Sender: TObject); begin // Добавляем новый элемент в колекцию ImageList1.Source // И присваиваем тексту кнопки имя свежесозданного элемента Button1.Text := ImageList1.Source.Add.Name; end; vSource := Self.Source.Add; // Здесь безо всякого Tag имеем уникальное имя vSource.Name if AName <> '' then // Если задали какоето своё имя AName то, присваиваем его, если такое имя уже есть, получаем исключение vSource.Name := AName; // Если не задали своё имя оставляем как есть // В любом случае дальше используем vSource.Name Но, как я понял, мои ответы отправляются в пустоту без попыток осмысления... Цитата Ссылка на комментарий
0 ENERGY Опубликовано 30 марта, 2017 Поделиться Опубликовано 30 марта, 2017 (изменено) Цитата Но, как я понял, мои ответы отправляются в пустоту без попыток осмысления Я все внимательно читаю, просто думал вы про Design Time говорите. Исправил на вариант без тэга. Но имя все равно используется чтобы идентифицировать слой, но уже стало гораздо легче . vDest := Self.Destination.Add; vLayer := vDest.Layers.Add; vLayer.SourceRect.Rect := TRectF.Create(TPoint.Zero, vSource.MultiResBitmap.Width, vSource.MultiResBitmap.Height); vLayer.Name := vSource.Name; Result := vDest.Index; Изменено 30 марта, 2017 пользователем ENRGY Цитата Ссылка на комментарий
Вопрос
rustam_d
DelphiXE8, Android.
Задача: загрузить в ImageList иконки 32х32 из базы данных.
Проблема: Не получается Transparent никак.
Как обычно перелопатил кучу форумов и ссылок и человеко-часов (эх vcl отнял бы 1 минуту...),
и удалось написать тестовое приложение.
Однако прозрачность никак не работает...иконка, что в тесте в поставке делфи идет,
цвет розовый. В дизайне все ок, а вот самому...
Закомментировал то что не помогает всеравно, но хотел показать что пробовал ).
Проверяю результат по иконке что на кнопке через action.
Иконка норм отображается, но с ней и розовый цвет...
procedure TForm1.Button4Click(Sender: TObject); var Layer: TLayer; c: TCustomSourceItem; b: TCustomBitmapItem; d: TCustomDestinationItem; begin d := ImageList1.Destination.Add; Layer := ImageList1.Destination[d.Index].Layers.Add; Layer.SourceRect.Rect := TRectF.Create(0, 0, 32, 32); c := ImageList1.Source.Add; Layer.Name := c.Name; //c.MultiResBitmap.TransparentColor := TAlphaColorRec.Fuchsia; b := c.MultiResBitmap.Add; b.Bitmap.SetSize(32,32); b.Bitmap.LoadFromFile('C:\Delphi\Images\GlyFX\glyFX\Icons\Aero\BMP\32x32\eject_blue_32_h.bmp'); //b.Bitmap.Clear(TAlphaColorRec.Fuchsia); Action2.ImageIndex := 3; end;
Ссылка на комментарий
24 ответа на этот вопрос
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.