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

Николай Ряполов

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

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

  • Посещение

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

  1.  

    1. TList не освобождает память своих элементов. А вот, если вы хотите, чтобы объекты-элементы тоже удалялись и есть TObjectList. Но освобождать память под объекты или нет, зависит от значения параметра AOwnedObject при создании списка.
    2. Да

     

    Таким образом подытожим выше сказанное:

    1. класс создаем таким образом:

    var
      LF: TListFile<T>;
    begin
      ...
      LF:= TListFile<T>.Create(True); //так мы говорим что надобно освобождать память автоматически
      try
        ...
        //тут работаем с нашим кодом
        ...
      finally
        LF.Free; //корректно подчищает за собой при установленном флаге AOwnerObject
      end;
    
    end
    

    Сам класс для хранения объектов меняем с TObjectList на TDictonary для увеличения производительности при сортировке массивов ввиду уже заложенных в "Словарь" алгоритмов на уровне системы.

    Спасибо огромное!

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

     

    Если код компилируется без ошибок и предупреждений, то можно считать, что это баг в Structure.

     

    P.S. Однако в вашем коде:

    • Совершенно лишняя реализация метода Clear. Если при создании вашего TObjectList в конуструкторе указать AOwnsObjects = True. То метод Clear из TList<> удалить и распустит ваши элементы.
    • Совершенно лишняя реализация метода Free. Этот метод базовый и присутствует во всех класса, так как он введен на уровне TObject.

    Изначально мой класс базировался на TList<T>, но по ряду причин после обработки 500к файлов память забивалась до 150 Мб, и методом TList.Free не освобождалась. Изменил базовый класс на TObjectList , память этим методом TObjectList.Free очищается полностью (100 итераций заполнение - очистка списка).

    Если я Вас верно понял то в описании класса достаточно описать так:

    TListFile<T: TFileInfo> = class(TObjectList<T>)
      private
        ...
        AOwnsObjects = True;
        ... 
        function GetAllSize: Int64;
      public
        ...
        property AllSize: Int64 read GetAllSize;
        // procedure Clear; overload; //тут можно удалить процедуру
        ...
      end;
    

    Или требуется сделать так:

    TListFile<T: TFileInfo> = class(TObjectList<T>)
      private
        ... 
        function GetAllSize: Int64;
      public
        ...
        property AllSize: Int64 read GetAllSize;
        constructor Create; overload;
        // procedure Clear; overload; //тут можно удалить процедуру
        ...
      end;
    
    ...
      constructor TListFile<T>.Create;
      begin
        inherited create;
        AOwnsObjects = True;
      end;
    ...
    

    Если Вас не затруднит еще один небольшой вопрос.

    Столкнулся со сравнением двух списков TListObject<T>, где Т: class содержащий информацию о файлах.

    Сравнивать как списки как:

     for T in ObjectList1 do
       if ObjectList2.IndexOf(T)>0 then
         // тут код сравнения
    

    однозначно позволяет установить что именно class 'T' в ObjectList1 точно соответствует class 'T' в ObjectList2. Так как отсутствие class 'Т' из ObjectList1 или малейшее его изменение в списке ObjectList2 однозначно требует проверки на внутреннюю проверку списков методом:

    var
      isModif: Boolean;
    begin
    ...
    
    for T1 in ObjectList1 do
    begin
      isModif := False;
      for T2 in ObjectList2 do
      begin
        if T1.Name = T2.Name then
        begin
    
          if (T1.Size <> T2.Size) or (T1.ModDate <> T2.ModDate) then
            T1.Status := fiModif // const fiModif = $00000001 
          else
            T1.Status := fiNoModif; // const fiNoNodif = $00000002
    
          isModif := True;
        end;
        if not isModif then
          T1.Status := fiCreate; // const fiCreate = $00000004
      end;
    end;     

    Если этот же класс реализовать через  TDictonary добавив в TKey T1.Name  и уже сравнение проводить согласно вхождению файлов в список ObjectList2 скорость сравнения достаточно увеличится или можно пренебречь реализацией?

  3. Доброго дня.
    Возник небольшой вопрос при создании классов.
    Выдержка из кода:

    //объявление классов
    
    TFileInfo = class
      private
        ...
    FSize: Int64;
      Public
        ...
    property Size: Int64 read FSize write FSize;
        procedure Free;
        ...
      end;
     
    
    TListFile<T: TFileInfo> = class(TObjectList<T>)
      private
    ...
    function GetAllSize: Int64;
      public
        ...
    property AllSize: Int64 read GetAllSize;
        procedure Clear; overload;
        ...
      end;
    
    // реализация классов
    ...
     
    procedure TFileInfo.Free;
    begin
      if Self <> nil then
        Destroy;
    end;
     
    ...
     
    
    function TListFile<T>.GetAllSize: Int64;
    var
      i: integer;
    begin
      Result := 0;
      for i := 0 to Count - 1 do
        Result := Result + Items[i].Size;
    end;
    
    ...
    procedure TListFile<T>.Clear; 
    var 
      i: integer; 
    begin 
      for i := 0 to Count - 1 do 
        Items[i].Free; 
      inherited Clear; 
    end;
    

    В общем IDE в секции "Structure" выдает ошибки "Undeclared identifier 'Free'('Size') at line №строки в процедуре Clear и GetAllSize
    Сам код не смотря на выдаваемые ошибки компилируются без Hints и Warnings
    Ткните меня плиз в мое не совершенство.

     

    P.S.

    Выкрутился таким путем

    ...
    function TListFile<T>.GetAllSize: Int64;
    var
      tb: T;
    begin
      Result:=0;
      for tb in List do
        if tb <> nil then
          Result := Result + tb.Size;
    end;
    ...
    procedure TListFile<T>.Clear;
    var
      tb: T;
    begin
      for tb in List do
        if tb <> nil then
          tb.Free;
      inherited Clear;
    end;
    

    Подскажите верно ли я поступил?

  4. Прикладываю Демо проект (пустая форма с фреймом) и файл фрейма.

     

    Стиль - пустой проект - Multi-Device Application

    Стили фрейма - все стандартные, ничего не трогал.

    Добавляю фрейм на форму Tool-Palette-Standart-Frames выбираю свой фрейм.

    Все в режиме Дизайна.

    Баг воспроизвелся отдельно от основного проекта.

    Среда XE7 Update1

    Win 8.1

    post-898-0-60913300-1425926820.png

     

    Архив с исходниками demo.zip

  5. Доброго дня.

    Решил попробовать начать работу с фреймами, но столкнулся со следующей ситуацией.

    При отображении фрейма на главной форме своевременно не отрисовываются события и перемещения курсора по компонентам фрейма.

    Фрейм добавляю с палитры компонентов.

    Плолучается примерно следующий вид:

       post-898-0-83056600-1425678384.png

    Как избавиться от этого?

  6.  

    если правильно понял вам нужна это:
     
    в FireMonkey и в Android свойстве TEdit добавлена FilterChar и выглядит это так:
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Edit1.FilterChar:= '0123456789';
    end;

     

     Из-за не знания основных свойств компонентов, городил такие Небоскребы ))))

    Благодарю, для Windows подходит, для Android так же не работает (

  7. Проблема заключается в следующем: мне нужно запретить ввод в TEdit всех символов, кроме цифр и запятой, а если вводится точка, то подменить ее на запятую.

    Запретить пробовал так:

    procedure TForm.EditKeyDown(Sender: TObject; var Key: Char);
    begin
    if not (Key in ['0'..'9', 'А'..'Я', 'а'..'я', 'A'..'Z', 'a'..'z', #8 ]) then Key:=#0;
    end;
    

    Символы продолжают вводиться. Запрет должен происходить при нажатиях на экранную клавиатуру Android'а.

    События KeyPressed я в XE6 не нашел.

     

    Я делаю проверку следующим образом

    procedure TForm1.Edit1ChangeTracking(Sender: TObject);
    var
      i: integer;
      sb: string;
    begin
      sb:=Edit1.Text;
      i:= low(sb); //так как разное начало строки в Win и Android платформах использую такую запись
      while i <= High(sb) do
      begin
        if Pos(sb[i],CharOfSimv)<1 then //CharOfSimv - простая строка вида '+-0123456789'
        begin
        delete(sb,i+1-Low(sb),1); // от платформы пляшем )
        end;
        inc(i);
      end;
      if sb<>Edit1.Text then
        ShowMessage('Вы ввели не верный символ');
      Edit1.Text:=sb;
    //ставим каретку в конец Edit
      Edit1.CaretPosition:=High(sb);
    //Update
      Label1.Text:= Edit1.Text;
    end;
    
    

    Update: При тестировании на платформе Android выявил следующее:

    1. При вводе с экранной клавиатуры в Edit текст после обработки не меняется на исправленный (12345р67)

    2. При передаче значения в Label (коммент Update) метке присваивается истинное значение (1234567)

    Как обойти данный баг?

    Платформа тестирования XE7 update1, Android 4.4.4 Sony Z1Compact

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