![]() |
|
Модераторы: Poseidon, Snowy, bems, MetalFan |
![]()
|
|
| Ne1tr1n0 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 120 Регистрация: 1.3.2009 Репутация: 6 Всего: 8 |
Добрый день!
Пытаюсь сделать просмотр миниатюр в ListView в виртуальном режиме. Делаю так: сначала получаю список файлов в каталоге, заношу в TStringList с помощью AddObject(sr.Name, TObject(IconIndex)) где IconIndex - индекс иконки файла в моем ImageList'e, полученный с помощью SHGetFileInfo. Далее запускается поток, в котором происходит следующее:
Причем эта ошибка возникает нерегулярно, на одной и той же картинке может нормально отработать, а может и выдать черный или белый квадрат. Если надо - могу полностью скинуть проект. Заранее спасибо. |
|||
|
||||
| Dapo |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 417 Регистрация: 18.4.2002 Репутация: нет Всего: 1 |
Кто такие BmpCanvas, FFileList, FImageList? F каком потоке они создаются? Почему Вы пилите сук на котором сидите: FBmp.Free; //убираем за собой
|
|||
|
||||
| Ne1tr1n0 |
|
||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 120 Регистрация: 1.3.2009 Репутация: 6 Всего: 8 |
BmpCanvas - заранее созданный битмап с нужным размером и выставленной прозрачностью. Создан в основном потоке программы (Фактически в FormCreate он создается).
FFileList и FImageList - свойства потомка от TThread (это который TThumbThread). Им при создании потока присваиваются ссылки на соответствующие поля формы.
Этот момент не совсем понял. Изображение ведь уже в ImageList'e, зачем оно дальше нужно? |
||||
|
|||||
| Illusion Dolphin |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1198 Регистрация: 3.5.2003 Репутация: 36 Всего: 63 |
Ошибки тут:
и тут:
С объектом Canvas работать из потоков нельзя, только через синхронизацию. -------------------- В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен. Шифрование и организация фотографий - Photo Database 4.5 |
||||
|
|||||
| Ne1tr1n0 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 120 Регистрация: 1.3.2009 Репутация: 6 Всего: 8 |
Вынес работу с Canvas в процедуру синхронизации. Но появились тормоза при прокрутке ListView например. Да и вообще интерфейс стал менее отзывчивым на действия пользователя.
Вот код:
Как теперь можно сделать? Добавлено через 3 минуты и 19 секунд ЗЫ: Я так полагаю основные тормоза создает StretchDraw. Возможно с ним что-нить можно сделать? |
|||
|
||||
| Illusion Dolphin |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1198 Регистрация: 3.5.2003 Репутация: 36 Всего: 63 |
Каждый из этих методов создаёт тормоза.
Assign одного TGraphic к другому везде реализован по-разному, в зависимостиот этого это можно выполнять в потоке или надо писать ручной Assign, который не будет затрагивать Canvas. Это зависит от конкретных типов изображений. StretchDraw - тут уже полегче (если не заморачиваться с качеством), есть готовые решения типа http://forum.vingrad.ru/forum/topic-49118/...size/index.html, они не работают с канвой, поэтому это можно делать в потоке без синхронизации. -------------------- В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен. Шифрование и организация фотографий - Photo Database 4.5 |
|||
|
||||
| Ne1tr1n0 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 120 Регистрация: 1.3.2009 Репутация: 6 Всего: 8 |
Поискал ещё насчет канвы и потоков - действительно пишут, что да, класс не Thread-safe, так что могут быть проблемы. Некоторые рекомендуют использовать методы Canvas.Lock и Canvas.Unlock соответственно сразу после того как создали битмап и закончили с ним работать. Вроде как это специальные методы Borland/Embarcadero (не знаю точно когда они появились), позволяющие работать с канвой в многопоточных приложениях. Попробовал у себя использовать - не помогает, хотя ошибок стало заметно меньше. Может быть стоит покопать поглубже в сторону этих Lock/Unlock? Есть смысл?
Вот код с блокированием канвы:
Насчет ресайза без использования канвы - спасибо, тоже посмотрю сейчас Это сообщение отредактировал(а) Ne1tr1n0 - 2.9.2012, 14:00 |
|||
|
||||
| MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 62 Всего: 128 |
Я тоже сталкивался с проблемами при работе с TBitmap/TPicture в потоке... На сколько я помню, TBitmap'у не удавалось порой выделять память при использовании его в отдельном потоке. При чем при работе в осн.потоке проблем не возникало.
Как решил проблему уже не помню, возможно свел вероятность ее возникновение к минимуму. -------------------- There are always someone smarter than you... |
|||
|
||||
| Illusion Dolphin |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1198 Регистрация: 3.5.2003 Репутация: 36 Всего: 63 |
Этот код блокирует все другие операции TBitmap.Assign ра время работы во всех потоках (инфа: исходники VCL)
Возможно это решит часть проблем, но я это обходил через неиспользование TCanvas в потоках. -------------------- В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен. Шифрование и организация фотографий - Photo Database 4.5 |
||||
|
|||||
| Ne1tr1n0 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 120 Регистрация: 1.3.2009 Репутация: 6 Всего: 8 |
Что-то все равно проскакивают ошибки. Может я что не так делаю?
|
|||
|
||||
| MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 62 Всего: 128 |
Ne1tr1n0, А FImgList - эт случайно не ссылка на компонент на форме? может лучше это (добавление картинки в ImageList) делать в основном потоке через Synchronize?
-------------------- There are always someone smarter than you... |
|||
|
||||
| Ne1tr1n0 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 120 Регистрация: 1.3.2009 Репутация: 6 Всего: 8 |
Так точно, она и есть. Это ImageList, привязанный к ListView'у.
Сейчас попробую вынессти добавление в ImageList в Syncronize. |
|||
|
||||
| Ne1tr1n0 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 120 Регистрация: 1.3.2009 Репутация: 6 Всего: 8 |
Да, так работает. И вроде даже не тормозит. Я тут просто решил поизвращаться, создал класс TItemData, в нем одним из полей TMemoryStream, так вот, после SmoothResize я запихивал тумбу в TJPEGImage, сжимал её, и сохранял в этот TMemoryStream. И добавлял каждый экземпляр класса в качестве связанного объекта в список файлов. А в ListView.OnGetImageIndex уже доставал из потока, преобразовывал в битмап и добавлял его в ImageList, назначая индекс только что добавленного элемента каждому ListItem'у. Тоже работало, но вариант MetalFan'a мне как-то поизящней кажется. Пожалуй тему можно закрывать, всем спасибо за обсуждение
|
|||
|
||||
| MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 62 Всего: 128 |
Ватэто изврат) Типа память экономил? А проблема скорее всего была в вызове метода TImageList.Add из потока... что вызывало скорее всего Update и выполнение кучи VCL-ного кода в доп.потоке вместо основного... Не зря ж везде советуют НЕ использовать VCL компоненты в доп. потоках без синхронизации или без понимания внутреннего устройства. -------------------- There are always someone smarter than you... |
|||
|
||||
| Ne1tr1n0 |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 120 Регистрация: 1.3.2009 Репутация: 6 Всего: 8 |
Ну можно и так сказать))) Только все равно тумба потом в ImageList'e оказывалась в виде битмапа, так что толку от такой экономии не особо было. Там просто одна из мыслей была ещё в OnCustomDrawItem самому её отрисовывать, но отказался от этой затеи.
И в каком-то примере видел подобную штуку, но там свой контрол был, внешне напоминающий ListView, но с собственным механизмом отрисовки, там как раз из жпега всё рисовалось. Тут ещё попутно вопрос возник. Не совсем правда к этой теме относящийся, так что может лучше и в отдельную ветку вынести. Вот делаю я значит в процедуре синхронизации такую штуку:
А после приведенного вызова Canvas.Draw видимо из-за того, что для FBmp в SmoothResize явно задается PixelFormat:=pf24bit у меня прозрачность теряется. И никакими TransparentColor/TransparentMode или PixelFormat:=pf32bit вернуть её не удается. В результате в ListView, если выделить элемент, то вокруг изображения образуется белый фон (вместо синего выделения). Выглядит это примерно так (у выделенного итема сверху и снизу относительно широкие белые полосы): Вот как бы от этого ещё избавиться? Спасибо. Это сообщение отредактировал(а) Ne1tr1n0 - 3.9.2012, 22:31 |
|||
|
||||
![]()
|
| Правила форума "Delphi: Общие вопросы" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Delphi: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |