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

Brovin Yaroslav

Администраторы
  • Постов

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

  • Посещение

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

    390

Ответы сообщества

  1. Пост Brovin Yaroslav - сообщение в Почему на мобильных платформах у меня не рисуется окружность? был отмечен как ответ   
    В вашем случае вы не задали тип кисти Canvas.Stroke. Более, чем уверен, что на устройстве там стоит TBrushKind.bkNone. Вашу проблему решит задание типа кисти TBrushKind.bkSolid.
    procedure TForm5.Image14Paint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); var EllipseRegion: TRectF; begin Canvas.Stroke.Kind := TBrushKind.bkSolid; Canvas.Stroke.Color := TAlphaColorRec.Red; EllipseRegion := TRectF.Create(TPointF.Create(100, 100), 20, 20); Canvas.DrawEllipse(EllipseRegion, 1); end;  Хорошая практика отрисовки в FMX полагает, что вы полностью инициализируете все кисти, необходимые вам для отрисовки.
    Так же обратите внимание, что канва для формы и всех контролах, размещенных на ней, всегда существует в одном экземпляре. И правилом хорошего тона, является использовать канву, переданную через параметры события отрисовки.
  2. Пост Brovin Yaroslav - сообщение в Как добавить изображение на кнопку SpeedButton? был отмечен как ответ   
    Обратите внимание на:
    Мою статью: http://blogs.embarcadero.com/yaroslavbrovin/2012/12/27/bitbt/ в которой я рассказал, как создать такой компонент. Этот пример можно модифицировать так, чтобы картинка менялась при нажатии. К этой статье также прикреплены исходники этой кнопки. Видео запись моего вебинара по теме статьи: http://www.youtube.com/watch?v=9cr-FGaDDR0&feature=youtu.be
  3. Пост Brovin Yaroslav - сообщение в Как убрать тулбар над виртуальной клавиатурой в iOS? был отмечен как ответ   
    Для управления виртуальной клавиатурой, в FIreMonkey есть два сервиса:
    Управление программным отображением и скрытием - FMX.VirtualKeyboard.IFMXVirtualKeyboardService Управление тулбаром над виртуальной клавиатурой - FMX.VirtualKeyboard.IFMXVirtualKeyboardToolbarService ​Именно второй сервис позволяет работать с тулбаром, добавлять и удалять кнопки.
     
    Чтобы скрыть тулбар, нужно:
     
    1. Запросить сервис IFMXVirtualKeyboardToolbarService у менеджера сервисов.
    var VKToolbarService: IFMXVirtualKeyboardToolbarService; begin TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardToolbarService, IInterface(VKToolbarService)); 2. Сказать сервису, что не нужно показывать тулбар, не забыв проверить, что сервис реализован в текущей платформе:
    if VKToolbarService <> nil then VKToolbarService.SetToolbarEnabled(False); Обратите внимание, что тулбар будет скрыт только в момент открытия клавиатуры.
  4. Пост Brovin Yaroslav - сообщение в Как правильно удалять контролы в RunTime? был отмечен как ответ   
    Добрый вечер,
     
    Главное, что нужно помнить по теме время жизни объектов - это то, что в мобильных платформах (Android и iOS) процесс удаления объектов отличается от поведения на настольных платформах (Windows и OSX). В мобильных платформах появился механизм ARC (Automatic Reference Counting - автоматический подсчет ссылок). Почитать описание (на английском), как это работает можно тут: Apple Developer. Для нас же, это означает, что все объекты имеют поле - счетчик ссылок (RefCount). Когда счетчик ссылок равен нулю, объект автоматически удаляется. Если кто-то присваивает ссылку на объект, то счетчик автоматически увеличивается на 1.
    property RefCount: Integer read FRefCount; // Свойство TObject Можно ошибочно подумать, что это связано со сборщиком мусора. Однако, это не так. При компиляции, компилятор автоматически вставляет в код служебные команды по увеличению и уменьшению счетчика ссылок. Поэтому объект физически уничтожится в тот момент, когда счетчик ссылок станет равным 0. В то время как сборщик мусора, удаляет объекты по своему внутреннему расписанию.
     
    Теперь о вашем вопросе. Когда вы создаете объект и указываете ему родителя, автоматически ваш объект попадает как минимум в список дочерних объектов TabItem1. А значит, автоматически счетчик ссылок на TCircle будет увеличен. Когда вы сохраняете ваш объект в массиве, это опять же автоматически увеличивает счетчик ссылок. Поэтому, чтобы удалить объект есть два способа:
     
    1. Вызвать метод TObject.DisposeOf. Это форсирует вызов деструктора, но не очищает память выделенную под объект. Это означает, что выполниться код деструктора, TCircle будет удален из списков, все ресурсы, которые окружность захватила будут распущены. Но сама память, которая была выделена из кучи под его хранение будет распущена, только в момент, когда больше не будет ни одной ссылки. Например, так:
    c[r].DisposeOf; c[r] := nil; 2. Убрать все ссылки, которые указывают на ваш объект. Это приведет к автоматическому удалению объекта. Убрать объект из структуры объектов, путем удаления удаления его из родительcкого контроkа Parent = nil, и затем вызывать Free и занилилить уже ссылку на объект в массиве. 
    c[r].Parent := nil; c[r].Free; c[r] := nil; // Или FreeAndNil(c[r]), в зависимости от типа c. Если больше ссылок на ваш объект нету, то данный код автоматически удалит объект c[r].
    Дополнение от RAD Studio XE6. В этой версии компилятор автоматически после вызова метода Free очистит указатель на объект. По этой причине дополнительно присваивание nil указателю на объект не требуется на мобильных платформах
    var A: TObject; begin A := TObject.Create; A.Free; // В этом месте A = nil на мобильных платформах. // На настольных платформах: A указывает на мусор end;  Чтобы осталась совместимость с настольными платформами, лучше использовать второй подход.
     
    P.S. Никогда не вызывайте деструктор напрямую, вызовом метода Destroy.
  5. Пост Brovin Yaroslav - сообщение в Как нарисовать точку на канве в FireMonkey? был отмечен как ответ   
    Добрый вечер
     
    В моей статье, я описывал способ работы с TBitmap. В вашем же случае, вы работаете с канвой. У канвы формы нету Bitmap. Поэтому ваш код падает при попытке вызывать Map у не существующего объекта.
     
    Для решения вашей задачи, нужно:
    Помнить о самое главной вещи при работе с канвой в FMX. Это то, что выполнять отрисовку можно только в определенный моменты времени (в отличии от VCL). Непосредственно, когда получен системный запрос на отрисовку сцены (формы), а именно в событиях OnPaint, OnPainting (в вашем случае у панели).  Знать, что канва существует в единственном экземпляре в рамках одной формы (опять же в отличии от VCL, где свою канву имеет каждый оконный контрол). Резюмирую, все выше сказанное.
    procedure TForm4.Panel1Paint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); var X, Y: Integer; PixelRegion: TRectF; begin Canvas.Stroke.Color := TAlphaColorRec.Red; for X := 0 to Floor(Panel1.Width) - 1 do for Y := 0 to Floor(Panel1.Height) - 1 do begin PixelRegion := TRectF.Create(TPointF.Create(X, Y), 1, 1); Canvas.DrawRect(PixelRegion, 0, 0, AllCorners, 1); end; end; Задаем обработчик на событие TPanel.OnPaint. Используя канву переданную через параметры, задаем цвет кисти и отрисовываем логические пиксели. Для закраски пикселей, я воспользовался обычной отрисовкой квадрата с шириной в 1 логический пиксель.
     
    Если речь идет об андроиде, то из-за возможного наличия экрана с повышенной плотностью пикселей (Screen Scale) это код для экранов со Scale отличных от 1 и не кратных 2, будет рисовать сдвоенные/размазанные линии. Чтобы этого избежать, нужно перед отрисовкой выполнить округление региона до физических пикселей при помощи метода TCanvas.AlignToPixel.
    procedure TForm4.Panel1Paint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); var X, Y: Integer; PixelRegion: TRectF; PixelPos: TPointF; begin Canvas.Stroke.Color := TAlphaColorRec.Red; for X := 0 to Floor(Panel1.Width) - 1 do for Y := 0 to Floor(Panel1.Height) - 1 do begin PixelPos := Canvas.AlignToPixel(TPointF.Create(X, Y)); PixelRegion := TRectF.Create(PixelPos, 1, 1); Canvas.DrawRect(PixelRegion, 0, 0, AllCorners, 1); end; end;
  6. Пост Brovin Yaroslav - сообщение в Есть ли в fmx класс TImageList? был отмечен как ответ   
    На данный момент (до версии RAD Studio XE5) FireMonkey не имеет компонент TImageList.
    Однако, для хранения графических ресурсов отлично подходит TStyleBook. Общая идея сводится к добавлению именованных графических ресурсов в TStyleBook в контейнере TImage. Затем мы каждому TImage задаем имя через StyleName. И затем в нашем коде уже по строковому идентификатору достаем нужную картинку.
     
    Рассмотрим теперь это на практике.
    Создадим приложение, которое будет вытаскивать картинку по имени из TStyleBook и отображать его в контейнере TImage.
     
    1. Создаем TStyleBook. Перетаскиваем его палитры компонентов (Tool Palette) в дизайнере на форму. Так же на форме я разметил кнопку и TImage для отображения выбранного изображения.

     
    2. Открываем дизайнер стилей и добавляем компонент TImage, путем перетаскивания TImage в корень Structure Panel (панель с деревом компонентов формы).

     
    3. В TImage загружаем картинку и называем картинку через TImage.StyleName. В моем случае изображение андроида и название  - 'android'. 


     
    4. Обратите внимание, что RAD Studio XE5 поддерживает картинки разного dpi для четкой отображения на экранах с разными dpi и Экранным масштабом (Scale). На рисунке выше, я загрузил два разрешения картинки, для обычных экранов, и экранов с удвоенной плотностью пикселей. Это актуально для мобильных платформ и OSX с экранами ретина.
     
    5. Пишем метод, который вытащить картинку по имени:
    function TForm4.GetImage(const AImageName: string): TBitmap; var StyleObject: TFmxObject; Image: TImage; begin StyleObject := ImageBook.Style.FindStyleResource(AImageName); if (StyleObject <> nil) and (StyleObject is TImage) then begin Image := StyleObject as TImage; Result := Image.Bitmap; end else Result := nil; end; Каждый объект FireMonkey TFmxObject предоставляет способ для поиска среди дочерних объектов объект с указанными именем StyleLookup. Доступ к корню всех стилей в StyleBook  является свойство TStyleBook.Style. Далее ищем у корня стиль с нужным именем картинки. Если стиля нету, то метод вернет nil. Иначе проверяем, что стиль есть и он экземпляр контейнера TImage. Далее просто выбираем картинку через свойство Bitmap.
     
    6. Вытаскиваем картинку и отображаем ее в TImage на форме.
    procedure TForm4.Button1Click(Sender: TObject); var Bitmap: TBitmap; begin Bitmap := GetImage('android'); if Bitmap <> nil then Image1.Bitmap.Assign(Bitmap); end; Вот в принципе и вся идея. Эту идею можно обобщить, сделав отдельный компонент с быстрой загрузкой картинок. Но это уже практика.
     
    Пример можно скачать тут: ImageBook.zip
  7. Пост Brovin Yaroslav - сообщение в Есть ли аналог TRichEdit из VCL? был отмечен как ответ   
    Добрый день,
     
    К сожалению, на данный момент (включительно RAD Studio XE6) в FireMonkey такого компонента нет. 
     
    Спасибо
×
×
  • Создать...