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

Brovin Yaroslav

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

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

  • Посещение

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

    390

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

  1. Такой вариант можно сделать:

    • Добавить контейнер (например TPanel, TLayout и тд), которую будет выдвигаться;
    • Добавить аниматор (TFloatAnimation) на y-позицию панели Panel.Position.Y и настроить параметры анимации согласно вашим требованиям. 
    • В момент наступления события запускать в ручную анимацию методом TFloatAnimation.Start

    P.S. TTabControl для этих целей лучше не использовать, потому что сам TabControl определяет все возможные варианты смены вкладок. Можно, конечно, переопределить класс TTabControl и добавить свои варианты смены, но этот способ сложнее и не обоснован для вашей задачи.

  2. Не все стили FireMonkey содержат стилизацию рамки окна. В вашем случае стиль не поддерживает стилизацию рамки. Поэтому свойство TForm.Border.Styling не оказывает никакого эффекта на стилизацию рамки. А в примере по ссылку используется другой стиль, который видимо поддерживает стилизацию рамки.

     

    Наличие поддержки стиля рамки окна можно проверить двумя способами:

    1. Непосредственно загрузив стиль и запустив приложение.
    2. Открыть стиль в дизайнере стиля в TStyleBook и проверить наличие стиля "windowborderstyle". Именно этот стиль используется для стилизации рамки окна.
  3. В вашем случае вы не задали тип кисти 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 полагает, что вы полностью инициализируете все кисти, необходимые вам для отрисовки.

    Так же обратите внимание, что канва для формы и всех контролах, размещенных на ней, всегда существует в одном экземпляре. И правилом хорошего тона, является использовать канву, переданную через параметры события отрисовки.

  4. Обратите внимание на:

    1. Мою статью: http://blogs.embarcadero.com/yaroslavbrovin/2012/12/27/bitbt/ в которой я рассказал, как создать такой компонент. Этот пример можно модифицировать так, чтобы картинка менялась при нажатии. К этой статье также прикреплены исходники этой кнопки.
    2. Видео запись моего вебинара по теме статьи: http://www.youtube.com/watch?v=9cr-FGaDDR0&feature=youtu.be
  5.  

    А почему когда пишу так:

    Image14.Canvas.Stroke.Color := TAlphaColorRec.Red;
    PixelRegion := TRectF.Create(TPointF.Create(100,100),20,20);
    Image14.Canvas.DrawEllipse(PixelRegion,1);
    То в Win всё видно, а на девайсе не видно?

     

     

    У меня просьба. На форуме пока негласное правило. Одна тема - один вопрос. В этой теме ответ уже был дан. Если вас интересует ответ на вашу ситуацию, оформите это отдельным вопросом. Так же нужно подробно описать вашу ситуацию. Чем подробнее и полнее будет описание вопроса, тем вероятнее на него и точнее будет ответ. Например в вашей ситуации нужно обязательно указать место, где вы пытаетесь выполнить отрисовку. А так же приложить скриншоты, подтверждающие, что на Windows и устройстве результат отрисовки разный.

     

    Спасибо за понимание.

  6. Для управления виртуальной клавиатурой, в 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);

    Обратите внимание, что тулбар будет скрыт только в момент открытия клавиатуры.

  7. Приложите, пожалуйста, скриншот вашей формы в дизайнере и развернутую панель структуры объектов (Structure) к вашему вопросу.

     

    Так на вскидку, для TViewPort3D нужно дополнительно указывать камеру. Потому что 3D приложение имеет уже встроенную камеру, а 2D в TViewPort3D нет.

  8. Добрый день,

     

    FireMonkey не имеет специальной поддержи заданий позиции курсора. Только сервис для получения текущей позиции мыши IFMXMouseService.

     

    Однако, вы можете сделать это самостоятельно.

  9. Добрый вечер,
     
    Главное, что нужно помнить по теме время жизни объектов - это то, что в мобильных платформах (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.

  10. Добрый вечер

     

    В моей статье, я описывал способ работы с TBitmap. В вашем же случае, вы работаете с канвой. У канвы формы нету Bitmap. Поэтому ваш код падает при попытке вызывать Map у не существующего объекта.

     

    Для решения вашей задачи, нужно:

    1. Помнить о самое главной вещи при работе с канвой в FMX. Это то, что выполнять отрисовку можно только в определенный моменты времени (в отличии от VCL). Непосредственно, когда получен системный запрос на отрисовку сцены (формы), а именно в событиях OnPaint, OnPainting (в вашем случае у панели). 
    2. Знать, что канва существует в единственном экземпляре в рамках одной формы (опять же в отличии от 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;
    
  11. На данный момент (до версии RAD Studio XE5) FireMonkey не имеет компонент TImageList.

    Однако, для хранения графических ресурсов отлично подходит TStyleBook. Общая идея сводится к добавлению именованных графических ресурсов в TStyleBook в контейнере TImage. Затем мы каждому TImage задаем имя через StyleName. И затем в нашем коде уже по строковому идентификатору достаем нужную картинку.

     

    Рассмотрим теперь это на практике.

    Создадим приложение, которое будет вытаскивать картинку по имени из TStyleBook и отображать его в контейнере TImage.

     

    1. Создаем TStyleBook. Перетаскиваем его палитры компонентов (Tool Palette) в дизайнере на форму. Так же на форме я разметил кнопку и TImage для отображения выбранного изображения.

    post-1-0-54560700-1388694754_thumb.jpg

     

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

    post-1-0-04195500-1388694739_thumb.jpg

     

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

    post-1-0-47577400-1388694758_thumb.jpg

    post-1-0-55951300-1388694756_thumb.jpg

     

    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

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