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

RoschinSpb

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

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

  • Посещение

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

    10

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

  1. Вот добавил пример для URL в ту же ветку, коль скоро там велось обстоятельное обсуждение.

    Также в ImageListDemo есть пример добавления картинки нарисованной вручную
    См. procedure TMainForm.AddSourceToItem(const Index: Integer);

  2. В 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;

    Здесь приведен простейший вариант загрузки картинки как есть, т.е. она будет хранится в исходном размере. На телефоне может и не хватить места.

  3. Вот тут пример загрузки из файла.

    Во-первых убедитесь, что MultiResBitmap содержит правильную картинку и размеры. Я бы сначала загрузил во временный TBitmap узнал его параметры (убедился, что он вообще что-то реально содержит) и уже потом присвоил его TCustomBitmapItem.Bitmap.Assign, а потом удалил. Кроме того для масштаба 1 кажется всегда есть картинка. Т.е. сделать надо примерно так:

        BI := Source.MultiResBitmap.ItemByScale(Scale, True, True);
        if BI = nil then
        begin
          BI := Source.MultiResBitmap.Add;
          BI.Scale := Scale;
        end;
    

    Во-вторых вы не тот индекс используете. Надо так:

        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;
    
  4. 39 минут назад, Major сказал:

    Можно ли как-то узнать список доступных кнопок

    Средствами Fire Monkey нельзя. И это относится не только к HardwareBack, Home, Menu но и вообще к любым клавишам на любой клавиатуре. Возможно можно как-то воспользоваться андроидными системными функциями, но например в Windows нету системных средств для определения наличия физических клавиш. Так что обработка горячих клавиш всегда должна дублироваться какими-то другими интерфейсными элементами, если конечно Вы не хотите намеренно скрыть что-то от обычных пользователей.

  5. Эмпирически выяснено, что vkHardwareBack есть на всех устройствах с Android (из тех, что проверялись). Это вообще специфическая для Android клавиша, для которой нет аналогов на других платформах.

    Остальное как получится. Теоретически можно нормальную клаву подключить, но это не проверялось.

  6. Цитата

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

    Не могу удержаться, Ярослав, но ты немного не прав. Можно удалять/изменять/загружать картинки со "съезжанием" и без оного. И хранятся они именно по уникальным именам

    ImageList.png

    Переименовывать картинки с уникальным именем можно в редакторе. 

    ImageList2.png

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

    Успехов

  7.  

    3 часа назад, ra.eremeev сказал:

    картинки в битмапе пропадают...

    У меня - Берлин 10.1

    Так в Битмапе или TImageList? Сделайте тестовый пример и направьте в QC. Баги обсуждать здесь бесполезно, т.к. ни кто уже не является работником Embarcadero.

  8. В 18.02.2017 в 15:41, Евгений Корепов сказал:

    А как решить проблему на андроид ТВ-приставках (тема уже дважды поднималась на форуме, но решения нет) - приложения Дельфи не реагируют на нажатие кнопки Ок с пульта управления (Инфракрасный пульт), на цифро-буквенные, меню, назад реагируют нормально. Товарищ по моей просьбе написал приложение на андроид студии, форма с кнопкой (фокус на кнопке), при нажатии выводится сообщение "Кнопка нажата" - на тв-приставки с пульта кнопка прекрасно нажимается. Аналогичное приложение на Дельфи (Berlin Update 2) никак не реагирует. 

    Из за этой проблемы путь на тв-приставки приложениям на Дельфи закрыт :-(

    Ну, тогда только: https://quality.embarcadero.com/secure/Dashboard.jspa

  9. 16 часов назад, Александр Урванцев сказал:

    а на будущее как для мобильных экранных клавиатур поступать?

    Моя рекомендация такая: стройте своё приложение таким образом, чтобы избежать обработки нажатий на клавиши. Если Вы не собираетесь создавать свой собственный текстовый редактор, то для подавляющего числа случаев вполне годится обработка горячих клавиш с использованием TActionList, в противном случае изучайте исходники, смотрите какие нужно реализовывать интерфейсы и ... "Безумству храбрых поём мы песню!"

  10. 8 часов назад, AlexShaman сказал:

    Berlin+ android , под win работает как надо.

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

  11. P.S. Отец Русской Демократии оно же функция Ord в коде обработки клавиш не нужны. Key сравниваете с константой vkXXX, KeyChar c буквой в апострофах, или #32 (решетка + код символа).

    Да и кстати, для мобильных экранных клавиатур такая обработка клавиш работать не будет.

  12. См. документацию источник знаний: KeyDown или TKeyEvent

    Key это скан код клавиши приведенный к виртуальным кодам клавиш windows. Это значение получается когда нажато некоторое сочетание клавиш к примеру Ctrl+<пробел>, такие нажатия последовательно передаются всем контролам, пока один из них не обработает его и не сбросит в 0. За некоторыми исключениями эти значения определяются физическим расположением клавиш, т. е. английская клавиша <A> будет всегда располагаться приблизительно в одном и том же месте и на Mac и на Win и в России и в Гондурасе.

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

    Так что для Ctrl+<пробел> надо использовать проверку if (Key =  vkSpace) and (ssCtrl in shift).
    Для проверки нажатия Ctrl+Ф надо использовать проверку if (Key =  vkA) and (ssCtrl in shift) и ни каких Key = Ord('Ф') потому, что неизвестно какая на этом месте будет буква на каком-нибудь Mac из Японии. И более того 

    Key = Ord('Ф') = $D4 - это зарезервированный код клавиши
    Key = Ord('ф') = $F4 - это VK_OEM_ENLW (Only used by Nokia)
    Key = Ord('a') = $61 - это vkNumpad1 (1 key numeric keypad)

    Но проще было бы создать действие (см. TActionList и TAction), назначить на него ShortCut выбрав одно из рекомендованных значений.

  13. В качестве послесловия.
    Деструктор объекта не может быть вызван внутри метода этого объекта (самоубийства запрещены). Всегда можно поставить точку останова на вызов метода Free/FreeAndNil. И внимательно посмотреть стек вызова, если где-то в стеке вызова присутствует разрушаемый объект, то это не правильно. Сложности добавляет то, что это не обязательно приводит возникновению AV, вполне может быть, что у вас всё будет работать без ошибок, а на другом компьютере, или на другой платформе с ошибками.
    Release на самом деле приводит к отложенному удалению не внутри вызывающего метода, т.е. объект просто помечается как готовый к удалению.

  14. 6 часов назад, Евгений Корепов сказал:

    Вот бы статью с иллюстрациями о правильном использовании TImageList. Интерфейс дизайн-части крайне нелогичный и запутанный. Мой опыт использования обычно заканчивается психозом из за того что компонент  рушит приложение из за ошибок с индексами. И фиг поймешь почему он падает при попытке обращения к некоему индексу 3 (где то в недрах своего кода), если в нем всего две картинки, которые используются на двух кнопках.

    Дайте пример, где он рушит приложение. Статьи есть на русском языке, найдёте, если захотите.

  15. Заведите TImageList (лучше на отдельном TDataModule), добавьте туда картинки в разных масштабах. На форму положите компонент TGlyph и установите свойства Images и ImageIndex.
    Glyph будет выбирать наиболее подходящую картинку с учетом и масштаба и размеров.

  16. В 26.01.2017 в 21:27, notricky сказал:

    Зачем читать тему целиком, когда можно просто в белом выйти.

    Да, действительно всю тему не прочитал, виноват. Вы тогда про 

        FOverlayShown := True;
        try
          Sleep(1000);
        finally
          FOverlayShown := False;
        end;
    

    тоже не читайте, ибо малодушный поиск лёгких путей — это не спортивно ;)

    Посыл сообщений физически это просто вызов некоторого метода объекта, только в отличие от обычных методов обработчики сообщений могут существовать, или не существовать. Смысл посыла сообщений в том, чтобы избавится от зависимостей, т.е. отправитель может не знать какие конкретно методы есть у получателя. Все ограничения связанные с многопоточностью остаются в силе. Главное ограничение это то, что нельзя работать с любыми интерфейсными элементами внутри потока без использования Sinchronize. Если с Sinchronize не работает, то надо написать об ошибке в QC, надеяться и ждать.

  17. FMX, также как и VCL так же как и вообще все объекты (за исключением некоторых специальных) не потокобезопасны. Т.е. напрямую использовать в потоке что-либо созданное вне этого потока нельзя, потому, что нельзя никогда... Всякие там формы кнопки и пр. взаимодействуют с другими формами кнопками и пр. контролами, так что даже если вы создаете и уничтожаете форму внутри потока (внутри метода Execute), то всё равно не явно Вы обращаетесь к другим объектам системы. Чтобы решить эту проблему все обращения к контролам надо делать в методе  Synchronize По этому ключевому слову ищите информацию в интернете и изучайте многопоточность.

    Но лучше просто не работайте с интерфейсом в потоке. В этом примере можно просто устанавливать и сбрасывать некий флаг FOverlayShown. К нему Вы можете обращаться из основного потока в любой момент (к FErrorMessage только после окончания работы потока). Обрабатывать OverlayShown можно например событии TAction.OnUpdate или хотя бы в TTimer.

    procedure TWorkThread.Execute;
    begin
      try
        FOverlayShown := True;
        try
          Sleep(1000);
        finally
          FOverlayShown := False;
        end;
      except
        on e: exception do
        begin
          FErrorMessage := e.Message;
        end;
      end;
    end;
    

    P.S. А лучше вообще не связывайтесь с потоками.


  18. В следующей версии вероятно появятся события:

    procedure TForm1.StringGrid1CellClick(const Column: TColumn; const Row: Integer);
    procedure TForm1.StringGrid1CellDblClick(const Column: TColumn; const Row: Integer);

    Пока ищите информацию в разделах посвященных TGrid и TStringGrid, там всё обсуждалось неоднократно.

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