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

xenon54

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

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

  • Посещение

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

    14

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

  1. Да я кажется уже разобрался.

    Видимо правильное удаление объекта в этом примере будет выглядеть так:

            for I := 0 to Form1.ComponentCount-1 do
            begin
              if Components[i] is TImage then
                if Components[i].Tag = 11 then
                begin
                  t2 := TImage(Components[i]);
                  t2.DisposeOf;
                  t2.Parent := nil;
                  t2 := nil;
    
                end;
    
    
            end;

    Т.е. нужно выполнить следующее:

    1. Удалить все ссылки на самого себя внутри объекта путем вызова деструктора через Free, но почему-то этого не достаточно, а вот DisposeOF справляется с поставленной задачей.

    2. Удалить все ссылки уже непосредственно в проекте которые делал сам, это ссылка в списке Children'ов у Form1, ну и саму ссылку/переменную t2.

  2. Вместо "string" в record нужно использовать "array [0..49] of char".

      TXSession = record
        name : array[0..49] of Char;
        name2 : array[0..49] of Char;
      end;
    
    

    А вообще, не уверен что эта тема относится к FM, разве что для не мобильной платформы можно было бы использовать string[50].

  3. Всем привет!

    Вопрос вроде бы легкий, но ....

     

    Накидал пример в котором есть структура(простейшая), массив из этих структур, ну и запись/чтение массива структур в/из файл(а).

    В процедуре чтения все идет на ура, проверяю в отладчике, все делается как надо. Как только строка переходит на "end" этой процедуры, выскакивает "Invalid pointer operation".

     

    Кому лень качать, вот часть листинга:

    type
      TXSession = record
        name : string;
        name2 : string;
      end;
    
      XRecordArray = array of TXSession;
    
    ......
    
    
    class procedure TXSessionClass.ReadTXSessions(var AXArray: XRecordArray);
    var
      FS : TFileStream;
      XSession : TXSession;
      i, arr_length : integer;
    begin
    
      FS := TFileStream.Create( 'Sess_arr.txt', fmOpenRead );
      FS.Read(arr_length, SizeOf(integer));
      SetLength(AXArray, 0);
      for I := 0 to arr_length-1 do
      begin
        FS.Read(XSession, SizeOf(TXSession));
        SetLength(AXArray, Length(AXArray) + 1);
        AXArray[Length(AXArray)-1] := XSession;
        //AXArray := AXArray + [XSession];
      end;
    
    
      FS.Free;
      FS := nil;
    
    end; //<-- Тут вываливается IPO
    

    test.zip

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

  5. Сделал еще 1 эксперимент:

    procedure TForm1.Button1Click(Sender: TObject);
    var
    i, j : Integer;
    t, t2 : TImage;
    begin
      for j  := 0 to 200 do
        begin
            t := TImage.Create(Form1);
            t.Parent := form1;
            t.Width := 50;
            t.Height := 50;
            t.Bitmap.LoadFromFile( TPath.Combine(TPath.GetDocumentsPath, '1.jpg') );
            t.tag := 11;
            t := nil;
    
            for I := 0 to Form1.ComponentCount-1 do
            begin
              if Components[i] is TImage then
                if Components[i].Tag = 11 then
                begin
                  t2 := TImage(Components[i]);
                  t2.Parent := nil;
                  t2.Free;
                  t2 := nil;
                end;
            end;
        end;
    end;
    

    Я так понял что я правильно реализовал способ номер 2 из этой темы. При картинке размером в ~200кб приложение крашится после 2-х кликов по кнопке. А вот если Free заменить на DisposeOf, то хоть утыкайся, приложение живет. В этой теме говорится что DisposeOf "форсирует вызов деструктора, но не очищает память выделенную под объект". Что это значит? И почему описанный выше пример не освобождает память?

     

    P.S.: Этот пример для Android, хотя я так понял в этом смысле поведение не отличается для IOS и Android.

  6. procedure TForm1.Button1Click(Sender: TObject);
    var
    t : TImage;
    begin
      t := TImage.Create(Form1);
      Memo1.Lines.Add(IntToStr( t.RefCount ) );
      t.Parent := form1;
      t.Width := 50;
      t.Height := 50;
      Memo1.Lines.Add(IntToStr( t.RefCount ) );
      t.Bitmap.Assign(image1.Bitmap);
      Memo1.Lines.Add(IntToStr( t.RefCount ) );
      t.tag := 11;
      Memo1.Lines.Add(IntToStr( t.RefCount ) );
    end;
    
    procedure TForm1.Button2Click(Sender: TObject);
    var
    i : Integer;
    begin
      Memo1.Lines.Add('---------------------');
      for I := 0 to Form1.ComponentCount-1 do
      begin
        if Components[i] is TImage then
          if Components[i].Tag = 11 then
          begin
            Memo1.Lines.Add(IntToStr( TImage( Components[i] ).RefCount )  + ' - ' + IntToStr( Components[i].Tag ) );
            TImage( Components[i] ).Parent := nil;
            Memo1.Lines.Add(IntToStr( TImage( Components[i] ).RefCount )  + ' - ' + IntToStr( Components[i].Tag ) );
          end;
      end;
    end;
    

    Вот результат memo после одного клика по button1 и одного клика по button2:

    5
    7
    7
    7
    ------------------------------
    9 - 11
    10 - 11

    После этого делаю еще 1 клик по button2 и получаю:

    7 - 11
    10 - 11
    1. Кто-нибудь может объяснить почему RefCount такой большой? Ведь по идее в самом начале на объект ссылается только сама переменная "T" и плюс ссылка в списке "components" у form1.
    2. После выхода из процедуры "button1click" локальная переменная(ссылка на объект)  "T" уничтожается и ее можно не считать, я правильно понял?
    3. Почему RefCount равен не 2, а 7?
    4. Почему если в конце процедуры "button1click" написать "t := nil;" картинка пропадает с формы, ведь на нее куча ссылок если верить RefCount'у
    5. Как тогда правильно уничтожить такой объект?

    Система IOS.

  7. Сам спросил, сам ответил...

    В FMX.ListView в функции определения индекса итема по абсолютной координате клика на ListView почему-то заложено такое поведение ( возвращает индекс последнего элемента если клик пришелся на область, вертикальная координата которой больше чем начало последнего итема). Вот так исправляется:

    function TCustomListView.FindItemAbsoluteAt(ViewAt: Integer): Integer;
    var
      Left, Right, Pivot, Value: Integer;
    begin
      UpdateItemLookups;
    
      if Items.Count < 1 then
        Exit(-1);
      if ViewAt < 1 then
        Exit(0);
      {
      if ViewAt >= FHeightSums[FHeightSums.Count - 1] then
        Exit(FHeightSums.Count - 1);
      }
      if ViewAt > FHeightSums[FHeightSums.Count - 1] + GetItemHeight( GetItemCount - 1 ) then
      Exit(- 1);
    
    
  8. Скажите пожалуйста, это нормальное поведение TListView? Создаем обычный TListView, добавляем в него 1 итем. Тыкаем мышкой в область TListView, но ниже итема в любом месте и каким-то чудом выделяется самый нижний итем, в данном примере он всего один. Если так и задумано {censored} то как с этим бороться

  9. Если я правильно понял (Вы сделали свой стиль для ListBoxItem и вставили туда свой RadioButton), то:

    1. Вам нужно присвоить "stylename" для этого RadioButton в стиле, допустим назвали вы его "MyRB".

    2. В обработчике событий ListBox'a - OnItemClick пишем:

    procedure TForm1.ListBox1ItemClick(const Sender: TCustomListBox;
      const Item: TListBoxItem);
    var
    i : integer;
    begin
       for i := 0 to ListBox1.count-1 do 
          ListBox1.ItemByIndex(i).StylesData['MyRB.IsChecked'] := False;
    
       Item.StylesData['MyRB.IsChecked'] := True;
    end;
    
×
×
  • Создать...