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

AngryOwl

Пользователи
  • Постов

    394
  • Зарегистрирован

  • Посещение

  • Победитель дней

    45

Сообщения, опубликованные AngryOwl

  1. Можно. Используйте события не OnClick или OnItemClick и т.д., а событие OnMouseUp у самого TListBox.

    Типа так:

    procedure TfmMain.lbxMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
    var
      LI : TListBoxItem;
      p : TPointF;
    begin
      if Assigned(Sender as TListBox) then
      begin
        LI := TListBox(Sender).ItemByPoint(X, Y);
    
        if Assigned(LI as TListBoxItem) then
        begin
          LI.IsSelected := True;
    
          TTask.Run(procedure
          begin
            if Button = TMouseButton.mbLeft then
              Do_какая-то_процедура(LI.Index) // просто пример
              else
              if Button = TMouseButton.mbRight then
                TThread.Synchronize(nil, procedure
                begin
                  p := MessageEvent.GetMousePos;
                  PopupMenu1.Popup(p.X, p.Y); // для вызова контекстного меню выделенного ListBoxItem
                end);
          end);
        end;
      end;
    end;

    P.S. Отмечу, что использовал TTask и TThread.Synchronize далеко не случайно!

    Во-первых TTask.Run запустит ваш обработчик нажатия на выделенный элемент в отдельном потоке, что не будет "тормозить" "выделение" самого ListBoxItem и вообще), а во-вторых - "внутри" вызванного потока сделал синхронизацию с основным потоком, при выводе контекстного меню для ListBoxItem, так как это гарантирует корректную работу с GUI в FMX.

  2. 1. Создайте свой стиль для ListBoxItem, например 'listboxitemMystyle', скопировав стандартный и переобозвав его. В своем стиле Итемов просто сделайте невидимым Detail. Или, что еще лучше, - храните Ваши ссылки в TagString Итема.

    2. В Style Designer, при редактировании Вашего listboxitemMystyle, вставьте TImage задайте ему необходимые свойства: выравнивание, размеры, отступы и т.д. (не забудьте сделать "растягивание" или что там Вам требуется - просто проверьте в дизайнере). И задайте Вашему TImage имя, например, 'myimagestyle'.

    3. При загрузке изображения я бы рекомендовал сначала загрузить изображение в созданный TBitmap, а потом уже грузить его в наш 'myimagestyle'. А самое оптимальное решение - загрузка изображений в "контейнер", в фоновом режиме, а при окончании загрузки, по событию, - отрисовка уже в самом итеме. В любом случае - сначала в битмап, а потом этот битмап в Итем. Иначе, вероятность того что битмап отрисуется в вашем случае - практически нулевая.

    4. Далее, при создании итемов:

    procedure ContactList_AddItem(Sender: TObject);
    var
      newItem : TListBoxItem;
      newBitmap : TBitmap;
    begin
      newItem := TListBoxItem.Create(nil);
      newItem.StyleLooup := 'listboxitemMystyle'; //  хотя будет проще не писать этого, а прописать в ListBox1.DefaultItemStyles.ItemStyle
      newItem.Text := 'текст';
      newItem.TagString  := тут может быть Ваша ссылка
      newBitmap := TBitmap.Create;
      newBitmap.LoadFrom  ....... // грузим картинку
      newItem.TagObject := newBitmap;
      newItem.OnApplyStyleLookup := MyItemApplyStyle;
      ListBox1.AddObject(newItem);
    end;
    
    procedure MyItemApplyStyle(Sender: TObject);
    var
      LI : TListBoxItem;
      tmpBitmap : TBitmap;
    begin
      LI := Sender as TListBoxItem;
      if Assigned(LI) then
      try
        LI.BeginUpdate;
    
        tmpBitmap := LI.TagObject as TBitmap;
        if Assigned(tmpBitmap) then
          LI.StylesData['myimagestyle.bitmap'] := tmpBitmap;
    
        //  тут вообще можно обновлять все что угодно в этом Итеме 
      finally
        LI.EndUpdate;
      end;
    end;

    Собственно все.

    Сорри если что не понятно -  писал "от руки", без проверки. Но вроде все просто.

  3. Под Андроид, все зависит от того - какая именно задача стоит? Цели этого "списка". Исходя из моего опыта, в некоторых случаях не обойтись без TListView (это не значит, что нельзя TListBox, просто у него ряд своих ограничений, и не только по скорости. Например - не очень "адекватная" работа с Touch. В смысле - прокрутка пальцем списка у TListBox не очень оптимизирована...)

    Поэтому - если Ваш список имеет не сложные элементы - я бы порекомендовал бы, наверное, переделать его на TListView. Покажите, или более подробно объясните - какие вообще элементы в каждом Итеме? Какие события обрабатываются? Прокрутка, нажатия, и т.д. В каждом Итеме картинки в каком виде? Их размер и положение? Они прямоугольные? И т.д.
    Чем больше деталей Вы предоставите - тем что-то более конкретное можно советовать в Вашем случае. Или даже помочь с кодом (в смысле - с примером реализации).

    Списки контактов в своей программе я делал - для Винды и Мака - TListBox, а для Андроида - TListView. И разница в коде - была всего в 4 десятка строк в общей сложности.

    Повторюсь - у каждого из этих компонентов есть свои преимущества и свои недостатки. Например: TListView - скорость работы, TListBox - более "гибкий" в плане создания любого Итема.

  4. Да еклмн - да хоть 100 элементов, хоть 500 - каждый со своей картинкой! Пишите аккуратно и грамотно - и "да прибудет с Вами "сила" (с)

    Ничего не тормозит, не глючит, все рисуется замечательно (что касается TListBox)!

    Я уже показывал пример. там речь не об этом, но везде TListBox - и в списке контактов и в сообщениях. Потому-что они намнооооого сложнее того (те итемы, с которыми я работаю), что видно. И их реализация на TListView возможна, но она сложнее на порядок.

    И еще момент! Скажите - как у Вас называется (в стиле) тот элемент в TListBoxItem, в котором содержится картинка? Не Icon ли случаем? Не помню точно какое название там по умолчанию, а смотреть сейчас лень, но сделайте свое наименование этого TImage, например 'myiconstyle' или еще как, и обновляйте через свой обработчик OnApplyStyleLookup.

    З.Ы. И я так понимаю - Вы делаете приложение именно под Win?

    З.З.Ы. И ничего переделывать не надо. Просто дайте скрин, или фрагмент скрина вашего приложения, если такое возможно. Визуально увидеть "проблему" - многого стоит. А если сделаете видео - совсем будет ясно. Хотя я и так понимаю - в чем у Вас проблема. И предложенное мной решение - работает.

    Не знаю - что там говорил Ярослав, но применение OnApplyStyleLookup - очень простое! Куда проще-то?

  5. 2 часа назад, Kitty сказал:

    А как все таки итему присвоить битмап через StylesData?

    Битмап нужно где-то хранить.
    При вызове OnApplyStyleLookup просто обновляйте его. Как в моем примере. Только в Вашем случае это будет TImage (как понимаю).

    var
      StyleObject: TFmxObject;
    ........
    
      StyleObject := FindStyleResource('picturechat') as TImage;
      if Assigned(StyleObject) then
        try
          TImage(StyleObject).Visible := // TRUE/FALSE
          TImage(StyleObject).OnClick := // Ваш обработчик, если надо
          if not MBitmap.IsEmpty then
            try
              if not GlobalUseGPUCanvas then
                TImage(StyleObject).Bitmap.Canvas.BeginScene;
              TImage(StyleObject).Bitmap := MBitmap; // ваш битмап
            finally
              if not GlobalUseGPUCanvas then
                TImage(StyleObject).Bitmap.Canvas.EndScene;
            end;
        finally
        end;

    типа того.

    'picturechat' - ваша картинка в стиле Итема

    а хранить изображения можно как контейнерах, так и читать из файлов (все достаточно быстро по скорости!)

    а вот с подгрузкой из инета - не знаю - Вам самим решать. Оптимально, думаю, загружать в контейнер, предварительно изменив размер до минимально необходимого.

    P.S. Забыл про StylesData

    можно так:

    вместо всего что написано выше, записать просто

    StylesData['picturechat.bitmap'] := MBitmap;

     

  6. Я [ZuBy] уважаю! Но не слушайте его, в данном случае! ))))

    Я с ним не согласен. Точнее - не совсем.

    У TListBox есть ряд свои преимуществ! Причем, зачастую, довольно существенных. Которые никакие TListView не перекрывают. По крайне мере пока.

    Во-первых - если речь идет о Винде, то это возможность плавного скроллинга. Чего нет у TListView. Не знаю кому как из разрабов, а рядового пользователя это часто бесит - прокрутка "рывками".

    Во-вторых - TListBox и его TListBoxItem'ы все же намного проще "рисовать". В смысле - создание своего шаблона пока еще намного проще чем у TListView. Вы можете для TListBox очень просто создавать свои элементы списка.

    Несмотря на то, что TListBox существенно "тормознее" TListView, часто его скорости вполне достаточно.

    Все, разумеется, зависит от Ваших конечных целей.

    А что касается картинок в Итемах TListBox, то нужно просто переопределить ApplyStyle.

    Создайте свою процедуру, например ItemApplyStyle;

    Присвойте, при создании Итема, свой обработчик. Например
    newItem.OnApplyStyleLookup := ItemApplyStyle;
    А в ItemApplyStyle сделайте обновление картинки. Типа так:

    procedure TContactActions.ItemApplyStyle(Sender: TObject);
    var
      StyleObject: TFmxObject;
      lbx : TListBox;
      LI : TListBoxItem;
    begin
      LI := Sender as TListBoxItem;
      LI.BeginUpdate;
      try
        StyleObject := LI.FindStyleResource('picture') as TCircle;
        if Assigned(StyleObject) then
          begin
            TCircle(StyleObject).Fill.Bitmap.Bitmap.Canvas.BeginScene();
            try
              TCircle(StyleObject).Fill.Bitmap.Bitmap := ____тут_ваш_битмап__;
            finally
              TCircle(StyleObject).Fill.Bitmap.Bitmap.Canvas.EndScene;
            end;
          end;
      finally
        LI.EndUpdate;
      end;
    end;

    Разумеется, все проверки и прочее - это уж Вы сами. И в моем примере это TCircle, а у Вас что - сами решите.

    Ну и можно для краткости (если там просто TImage) не писать все через StyleObject, а покороче, через StylesData['_имя_.bitmap'] и т.д.

    Ну и что на Delphi - не обессудьте! ) Смысл тут простой.

    Думаю, что в целом идея ясна.

  7. 29 минут назад, wamaco сказал:

    У меня ругается на троян

    2016-12-24_0159.png

    360 Total Security - тот еще "антивирусник"! )))

    Давайте уже - если кто-то на что-то хочет поругаться - киньте это для начала в www.virustotal.com (например)

    Ничего не хочу сказать - но у меня ничего ни на что не ругнулось!

    И я бы скорее сказал - что 360 TS - большее зло, чем некоторые "вирусы" ...

  8. 3 часа назад, ZuBy сказал:

    не смог воспроизвести вашу ситуацию, есть подозрение на стиль. попробуйте при добавлении Item'a, прогрузить стиль вручную

    LBScroll.zip

    Во-первых - спасибо за подсказку (прогрузить стили)!
    А во-вторых - решение конечно еще тот "костыль", но работает.

    Перед тем как прокрутить TListBox в конец (любым способом), потребовалось пробежать по всем Итемам и применить им стиль!

    for i := 0 to TListBox(Sender).Items.Count - 1 do
      TListBox(Sender).ListItems[i].ApplyStyleLookup;

    И только после это - все работает как надо. И никак иначе...

    Есть, конечно, над чем поработать - например на скоростью. Но пока меня решение устраивает.

    Спасибо! Вопрос решен!

     

  9. Только что, rakhmet сказал:

    Хм...

    Выглядит замечательно. Спасибо за сэмпл. Я как-то не подумал о том, чтобы ручками ВСЁ окно перерисовать самостоятельно. Теперь осталось разобраться, как это работает.

    "Ищите и обрящите" (с)))
    На форуме есть темы, связанные с этим вопросом. В том числе и я где-то тут описывал - как делать такие формы.

  10. Речь идет (RageGod спрашивает) - что именно Вы используете для этого "списка"?

    Если TListBox и используете TListBoxItem, то все очень просто! Измените стиль для 'listboxitemstyle', добавив ему линию или битмап с выравниванием Bottom, толщиной в один пиксель (типа того...) и все.

    Или создайте свой новый стиль для Итемов и применяйте его в нужных случаях.

    А если Вы используете TListView, то раньше надо было делать все "ручками", в коде, но это не сложно совсем. А сейчас вообще можно в конструкторе!

  11. 15 минут назад, rakhmet сказал:

    Т.е. проще уйти на тот же XCode/Swift, чем найти "транслированное sdk под делфи" - я правильно понял намёк?

    Ну если Вы уже кодили на XCode/Swift, то в Вашем случае возможно и проще... Смотря какая конечная цель.

    А если говорить именно о Вашей проблеме, то что Вам мешает сделать свое окно полностью, в шапке которого можете размещать хоть проигрываемое видео, не говоря уже про кнопочки с битмапами. Причем окна свои можно сделать "вылитыми" макосовскими... Хотя не вижу в этом необходимости (как по мне - так они не очень удобны).

    Сделайте свой стиль, свои окна, с тенями, с кнопками с битмапами. С чем угодно!

  12. 8 минут назад, kami сказал:

    Ну, с моей стороны будет костылирование, а не решение, но...

    Попробуйте сделать отложенный скролл вниз, возможно что в фоне еще идут какие-то вычисления...

    Например:

    
    TTask.Run(TThread.Queue(ScrollToLast));

     

    Спасибо! Но, к сожалению, эффект тот же...

  13. Привет друзья!

    Возникла странная ситуация при работе с TListBox. А именно - при попытке прокрутки списка в его конец.

    Условно:

    - есть список итемов (сообщения чата);

    - загрузка сообщений происходит в процедуре "синхронизированной" с главным потоком и заключена в TListBox(listbox1).BeginUpdate  и TListBox(listbox1).EndUpdate;

    - все замечательно грузится

    НО! После загрузки Итемов требуется прокрутить список в его конец. И вот тут начинаются "приколы".

    Как только не пытаться прокрутить список в его конец (разные способы, см.ниже) - всегда получается, что список прокручивается до конца, но немного "откатывается" вверх. Размер его автоматического скролла "обратно" зависит от количества Item в TListBox! Чем больше кол-во Item - тем больше назад откатывается скролл.

    Способы прокрутки в конец списка - значения не имеют. Всегда одно и то же.

    procedure TChatListBoxEx.ScrollToLast;
    var
      Item: TListBoxItem;
    begin
    // ВАРИАНТ 1
      Item := ListItems[Items.Count - 1];
      if Assigned(Item) then
        ScrollToItem(Item);
    
    // ВАРИАНТ 2
      ViewportPosition:= TPointF.Create(0, Item.ParentedRect.Top);
    
    // ВАРИАНТ 3
      ScrollBy(0, ViewportPosition.Y - Item.ParentedRect.Top);
    
    // ВАРИАНТ 4
      BeginUpdate;
      try
        ItemIndex := Items.Count - 1;
      finally
        EndUpdate;
      end;
    end;

    Предупреждая ваши вопросы, сразу скажу - пробовал и другие варианты, просто перечислять не стал все. Пробовал и эмитировать нажатие клавиши END при "активном" списке.

    Все синхронизируется, типа 

    TThread.Synchronize(nil, listbox1.ScrollToLast);

    Эффект всегда один и тот же...

    НО! Если загрузить список, независимо от кол-ва элементов списка, а потом в программе вызвать ScrollToLast, подождав некоторое время, а не сразу, например по нажатию на какую-нибудь кнопку, то список прокрутится в конец НОРМАЛЬНО!

    Будьте добры - кто сталкивался с подобной ситуацией, или кто что-то может посоветовать?

    Или наши Гуру смогут ответить на этот вопрос?

    Видео, чтобы было понятнее что происходит, прилагаю.

    RAD Studio 10.1 Berlin (эффект наблюдается на всех версиях Windows - XP, Vista, 7, 8, 10. На других ОС пока не пробовал...)

    Заранее благодарен!

    P.S. Возник вопрос (как вариант решения проблемы) - как узнать, что произошло событие окончания отрисовки TListBox? А именно - список заполнился, выполнилась отрисовка и можно прокручивать.

  14. Добрый вечер, друзья!

    Кто в курсе, подскажите - возможен ли плавный скроллинг содержимого TListView при работе приложения под Windows?

    Если с мобильным вариантом все ОК, на "автомате" - т.е. плавный скроллинг там работает по умолчанию, то с работой под Windows что-то не понятно как это включить/реализовать.

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

    TScrollBox(__listbox1___).AniCalculations.Animation := True;

    А есть ли что-то аналогичное для TListView?

    Заранее благодарен за ответы!

  15. 16 часов назад, wassail сказал:

    То-есть использовать под Windows с компонентами FireMonkey напрямую из библиотек OpenGL или Vulkan нельзя? (на канве или в TImage ). А из DirectX?  Ну а как тогда, например, подключать шейдеры из внешних файлов для создания различных эффектов? Тоже нельзя? Просветите, пожалуйста.

    Тут я, к сожалению, не советчик. У меня нет такого опыта работы с использованием Firemonkey и OpenGL или Vulkan.

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