Elektroda.pl
Elektroda.pl
X
Relpol
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

DELPHI 7 - Czy idzie przesuwać rekordy w Strumieniach?

TomekMus 04 Gru 2010 22:27 2167 28
  • #1 04 Gru 2010 22:27
    TomekMus
    Poziom 17  

    Witam,



    Code:
    \
    
    type
      TDane = class
        Nazwa : String[255];
        Font : record
                     .................
                 end;
        Adres : record
                      Ulica : String[100];
                     ..................
                  end;
        Opis   : record
                      .................
                   end;     
        //... reszta rekordu około 30zmiennych
      end;

    var
       Dane : TDane;






    Buduje sobie jakiś rekord i używając Plików Strumieniowych czy da się zrobić coś takiego by po wczytaniu samej Nazwy z rekordu TDane do Memo w ilości x rekordów tak by przesuwająć Nazwę (w góre, w dół, dodawać, usuwać) fizucznie całę rekordy SizeOf (Dane) przesuwać i usuwać wewnętrzne rekordu i wszystko wy się przesuwało w pliku strumienia, pamięci strumienia, lub bazie strumienia

    0 28
  • Relpol
  • #3 04 Gru 2010 23:01
    TomekMus
    Poziom 17  

    Chodzi mi o to że Strumień z zawartością np 100 rekordów TDane i do komponentu Memo dodaję nazwę odczytaną ze rekordu np:

    for i:=0 to Strumień.Size -1 do
    begin
    Memo1.Items.Add (Dane[i].Nazwa); //To oczywiśnie Dane[i] podane jak by to był plik typu Plik : File;
    end;

    I jak przesune jakiś rekord wyżej lub niżej to mi również w strumieniu się przenoszą kolejnością rekordy.

    Jak usunę np 4 rekord to wszystkie od 5 rekordu przesuną się wyżej itd.

    DELPHI 7 - Czy idzie przesuwać rekordy w Strumieniach?

    0
  • Pomocny post
    #4 04 Gru 2010 23:07
    Dżyszla
    Poziom 42  

    Strumienie raczej nie służą do edycji danych, jak sama nazwa mówi.
    Aby móc manipulować danymi musisz wczytać je do stosownej struktury (np tablicy dynamicznej lub listy), następnie tam przykładowo wykonać zmianę kolejności i ponownie zapisać.

    0
  • #5 04 Gru 2010 23:56
    TomekMus
    Poziom 17  

    A jak to zrobić w delphi, klas użyć by sprawdziało się moje zastosowanie - docelowo wykorzystam CheckListBox?

    0
  • Relpol
  • #7 05 Gru 2010 10:33
    TomekMus
    Poziom 17  

    Można malutki przykładzik bo się torszkę pogubiłem :)

    0
  • #9 05 Gru 2010 11:03
    TomekMus
    Poziom 17  

    Code:
    function AddObject(const S: string; AObject: TObject): Integer; virtual;


    Nie bardzo rozumiem te przykłady ponieważ nie umiem powiązać do mojego rekordu.

    Nie weim czy dobrze rozumiem że pod zmienną S przechowuje jakąś nazwę a pod AObject to będzie mój rekord z danymi?

    0
  • #10 05 Gru 2010 11:26
    Dżyszla
    Poziom 42  

    TCheckListBox też ma własność tego typu. To spod S jest wyświetlane. To spod AObject jest przechowywane w tablicy Objects, czyli u Ciebie zrzutowany na TObject rekord (choć łatwiej by było, abyś zamiast rekordu użył klasy).
    Teraz odczytując po kolei elementy z tablicy obiektów odczytasz porządek. Wykorzystując funkcję Replace możesz zamieniać miejscami dwa elementy, ergo - przenosić w górę i w dół - kolejność rekordów zostanie zmieniona w tej wirtualnej tablicy.

    0
  • #11 05 Gru 2010 12:37
    TomekMus
    Poziom 17  

    Nie mogę znaleść poleceń w CheckListBox.Items.....:
    - ergo
    - replace

    0
  • #13 05 Gru 2010 16:00
    TomekMus
    Poziom 17  

    Czy chodzi o Move ?

    0
  • #15 05 Gru 2010 22:53
    TomekMus
    Poziom 17  

    Cofam myśl z Move - teraz ja pomyliłem

    Jak wyciągnąć dane po włożeniu je do

    Code:
    CheckListBox1.Items.AddObjects ('Rekord', Dane);

    0
  • #17 05 Gru 2010 23:09
    TomekMus
    Poziom 17  

    OK tylko jak przypisać odpowiednią zmienną umieszczoną pod danym indexem listy
    do zmiennej którą mogę przetworzyć w progrmie:

    Podam kod prymitywnie ale tak bym przekazał i docelowo zrozumiał ide przypisania w drugą stronę

    Code:
    Dane.Nazwa:=CheckListBox1.Objects[CheckListBox1.ItemIndex].Nazwa;
    

    Dane.Adres.Ulica:=CheckListBox1.Objects[CheckListBox1.ItemIndex].Adres.Ulica;


    Ponieważ zastanawiam się jeśli użyje rzutowania to z kąd mam pewność że rzutuję odpowiednią zmienną pod moją którą chcę(potrzebuję przetworzyć), jeśli progam mój ma po 10 zmiennych typy Byte, Integer, Word, ShortString....

    0
  • #18 05 Gru 2010 23:24
    Dżyszla
    Poziom 42  

    Ale nie musisz poszczególnych pól przepisywać. Tworząc nowy obiekt po prostu zapamiętujesz go właśnie na tej liście. Potem do zmiennej możesz wprost przepisać cały obiekt.
    Samo rzutowanie także musi odbyć się na poziomie całej klasy (lub typu rekordowego).

    Code:

    var
       Klasa: TKlasa;
    begin
       Klasa:=TKlasa.Create;
       Klasa.Pole:=1;
       Klasa.Nazwa:='Pokaż';
       CheckListBox.Item.Add(Klasa.Nazwa,Klasa);
       Klasa:=nil;
       Klasa:=CheckListBox.Items.Objects[0];
       Klasa.Pole:=Klasa.Pole+1; //=2
    end;

    Pamietaj tylko o zwolnieniu podczas usuwania elementu listy.

    0
  • #19 06 Gru 2010 00:01
    TomekMus
    Poziom 17  

    Myślę że zrobuiłem tak jak kazałeś lecz wychodzi mi błąd zgodności typów, by nie owijać w bawełne dodam przykładawy projekt w którym możesz zobaczyć gdzie popełniam błąd.

    0
  • Pomocny post
    #20 06 Gru 2010 02:37
    xanio
    Poziom 27  

    Jeżeli kolega pisał z głowy bez testowania to ja sugeruję (również bez testowania) zamiany linijki:

    Code:

       Klasa:=CheckListBox.Items.Objects[0];


    na:

    Code:

       Klasa:=TKlasa(CheckListBox.Items.Objects[0]);


    lub

    Code:

       Klasa:=CheckListBox.Items.Objects[0] as TKlasa;

    0
  • #21 06 Gru 2010 09:16
    TomekMus
    Poziom 17  

    Czy użycie:

    Code:
    CheckListBox1.DeleteSelected;

    zwalnia mi wszystko z pamięci które dodałem wcześniej:
    Code:
    CheckListBox1.Items.AddObject(Klasa.Nazwa, Klasa)


    I jeszcze jak zastosować Drag & Drop jak wykorzystuje AddObject

    0
  • Pomocny post
    #22 06 Gru 2010 11:55
    arnoldziq
    Moderator Programowanie

    TomekMus napisał:
    Czy użycie:
    Code:
    CheckListBox1.DeleteSelected;

    zwalnia mi wszystko z pamięci które dodałem wcześniej:
    Code:
    CheckListBox1.Items.AddObject(Klasa.Nazwa, Klasa)

    To pytanie, czy stwierdzenie ?
    Jeżeli stwierdzenie, to całkowicie błędne. Jeżeli pytanie, to odpowiedz brzmi : nie.
    Metoda DeleteSelected usuwa z listy tylko odpowiednie (zaznaczone) elementy, ale nie zwalnia pamięci obiektów do nich przypisanych. Obiekty dalej "żyją własnym życiem" gdzieś w pamięci.
    Jeżeli chcesz zwalniać pamięć obiektów, to musisz napisać swoją własną procedurę ich zwalniania. Może ta procedura wyglądać np. tak :
    Code:
    procedure TForm13.Button1Click(Sender: TObject);
    
    var
     i : integer;
    begin
     for i := 0 to (CheckListBox1.Items.Count - 1) do begin
       if CheckListBox1.Selected[i] then
        begin
         if assigned(CheckListBox1.Items.Objects[i]) then
          begin
           TKlasa(CheckListBox1.Items.Objects[i]).destroy;
           CheckListBox1.Items.Objects[i]:=nil;
          end;
       end;
     end;
     CheckListBox1.DeleteSelected;
    end;

    0
  • #23 08 Gru 2010 01:46
    TomekMus
    Poziom 17  

    A jak zaktualizować istniejący obiekt:

    Co już mamy:
    - tworzenie obiektu
    - odczytanie obiektu
    - usuniecie obiekty
    - brak aktualizacji obiektu (zniany jednej zmiennej lub wszystkich) ????

    0
  • Pomocny post
    #24 08 Gru 2010 10:07
    arnoldziq
    Moderator Programowanie

    TomekMus napisał:
    - brak aktualizacji obiektu (zniany jednej zmiennej lub wszystkich) ????

    Zazwyczaj nie zmienia się obiektów na liście. Wyrzuca się, po prostu, niepotrzebny element i wstawia nowy.
    Oczywiście, jeżeli stwierdzisz, że chcesz aktualizować obiekt dołączony do listy, to można to zrobić, podmieniając jego wskaźnik w liście obiektów.
    Każda lista ma jakiś mechanizm sortowania, więc "porządkowanie" listy nie powinno nastręczać problemów, gdy usuniesz i dodasz jakiś obiekt w "normalny" sposób.

    0
  • #25 08 Gru 2010 12:45
    TomekMus
    Poziom 17  

    Bardziej by mnie interesowało metoda podmienienia wskaźnika - ponieważ każda zmiana w moim programie jest robiona automatycznie:

    - Edit1.OnChange - czyli piszać literka po literce zawsze zmieniam dane w rekordzie (niestety nie mogę tego zmienić by zachować poprawne działanie programu na button "Zapisz")

    0
  • Pomocny post
    #26 08 Gru 2010 13:20
    arnoldziq
    Moderator Programowanie

    TomekMus napisał:
    Bardziej by mnie interesowało metoda podmienienia wskaźnika - ponieważ każda zmiana w moim programie jest robiona automatycznie:
    Tego nie rozumiem. Przecież napisałem ci jak to zrobić...
    TomekMus napisał:
    - Edit1.OnChange - czyli piszać literka po literce zawsze zmieniam dane w rekordzie (niestety nie mogę tego zmienić by zachować poprawne działanie programu na button "Zapisz")
    Nie musisz tego robić w ten sposób. To strata czasu i zasobów.
    W procedurze wywoływanej przez OnChange, ustawiaj sobie tylko zmienną, np:
    Code:
    Zmieniono_zawartosc:=True;
    A przy zakończeniu ("Zapisz"), po prostu sprawdzaj czy coś zostało zmienione. Jeżeli tak, to czytasz poszczególne, zmienione wartości i zapisujesz. Jeżeli nie, to wychodzisz, bez zapisu.

    0
  • #27 08 Gru 2010 13:31
    TomekMus
    Poziom 17  

    Znalazłem na jakimś forum coś takiego czyli na wskaźnikach, może iść tą drogą i poprostu po wskaźniku można usuwać bezpośrednio z pamięci itp:

    Zastanawiam się tylko jak zmienić wartość już istniejącego rekordu w tym przypadku.


    Code:

    AddObject adds a Pointer to your object together with the string you add to the list. So once your procedure (Button1Click?) ends, the data will disappear and vanish.
    What you need to do, is declare your record like this:

    type
    PData = ^TData;
    TData = record
    Text1, Text2, Text3: string[50];
    end;


    Next, you could add your record like this:


    var
    MyData: PData;
    begin
    New(MyData);
    MyData^.Text1 := Edit1.Text;
    MyData^.Text2 := Edit2.Text;
    MyData^.Text3 := Edit3.Text;
    ListBox1.Items.AddObject(Edit1.Text, MyData);
    end;


    and when you are done and want to remove a menu item, do NOT forget to free the memory you reserved for your record:


    ..
    Dispose(ListBox1.Items.Objects[TheItemToDelete]);
    ListBox1.Items.Delete(TheItemToDelete);
    ..

    0
  • Pomocny post
    #28 08 Gru 2010 14:37
    arnoldziq
    Moderator Programowanie

    Można i tak.
    Z tym, że operujesz na rekordzie, więc tracisz wszystkie właściwości klasy TObject. Równocześnie, nikt nie operuje na obiektach, używając do tego TCheckBoxList, bo wspomniany komponent nie ma po prostu do tego narzędzi. Dodając obiekt do TCheckBoxList, możesz się do niego odwołać tylko przez jego kolejny indeks, a to trochę za mało :). Musiałbyś stworzyć dodatkowe procedury, które w wygodniejszy sposób będą operować na tych obiektach.
    Przeanalizuj sobie zamieszczony poniżej kod.Co prawda operuje on na TList, ale zasada jest podobna. I wykorzystując tego typu strukturę, możesz przenieść dane do dowolnej listy.
    Struktura danych, w tym przypadku jest tworzona automatycznie i możesz na tych danych operować, odwołując się nie do elementów listy, ale do poszczególnych obiektów, które znajdują się w pamięci. jeżeli chcesz coś z listy usunąć, to wystarczy ustawić GroupID np z 1 na 0 i element nie będzie wyszukiwany przy kolejnych operacjach, a zostanie usunięty z pamięci w momencie niszczenia głównego obiektu listy : TTagList.

    Code:
    unit NewTagList;
    
    interface
    uses
      Classes, SysUtils;
    type
      TTagListItem = class(TObject)
        ItemID      : integer;
        GroupID     : Integer;
        Name        : String;
        Date        : TDateTime;
        Client      : String;
      end; {class}

      TTagList = class(TObject)
      private
        fItems:TList;
      public
        constructor Create;
        destructor Destroy; override;
        procedure Clear;
        function Count:integer;

        function AddNew( ItemID, GroupID : integer; Name:string ):TTagListItem;
        function AddItem( ItemID:integer; Name:string ):TTagListItem;
        function AddItemWithGroup( ItemID, GroupID :integer; Name:string ):TTagListItem;

        function ItemByID( ItemID:integer ):TTagListItem;
        function ItemByIDandGroup( ItemID,GroupID : integer ):TTagListItem;
        function Items( Index:Integer):TTagListItem;
      end; {class}

    implementation
    //======================================================================
    constructor TTagList.Create;
    begin
      fItems := TList.Create;
    end;

    destructor TTagList.Destroy;
    begin
      Clear;
      fItems.Free;
    end;

    procedure TTagList.Clear;
    var




      idx:integer;
    begin
      for idx := 0 to (fItems.Count-1) do begin
        TTagListItem(fItems[idx]).Free;
      end; {for}
      fItems.Clear;
    end;

    function TTagList.Count:integer;
    begin
      Result := fItems.Count;
    end;

    function TTagList.AddNew( ItemID, GroupID : integer; Name:string ):TTagListItem;
    begin
      if GroupID=0 then Result := ItemByID( ItemID )
      else Result := ItemByIDandGroup( ItemID, GroupID );
      if (Result = NIL) then
      begin
        Result := TTagListItem.Create;
        Result.ItemID      := ItemID;
        Result.GroupID     :=GroupID;
        Result.Name        :=name;
        Result.Date        :=0;
        Result.Client      :='';
        fItems.Add(Result);
      end; {if}
    end;

    function TTagList.AddItem( ItemID:integer; Name:string ):TTagListItem;
    begin
      Result:=AddItemWithGroup(ItemID,0,Name);
    end;

    function TTagList.AddItemWithGroup( ItemID, GroupID :integer; Name:string ):TTagListItem;
    begin
      Result:=AddNew(itemID,GroupID,Name);
    end;

    function TTagList.ItemByIDandGroup( ItemID,GroupID : integer ):TTagListItem;
    var
      idx:integer;
    begin
      for idx := 0 to (fItems.Count-1) do begin
        Result := TTagListItem(fItems[idx]);
        if (Result.ItemID = ItemID) and ((Result.GroupID = GroupID)) then Exit;
      end; {for}
      Result := NIL;
    end;

    function TTagList.ItemByID( ItemID:integer ):TTagListItem;
    var
      idx:integer;
    begin
      for idx := 0 to (fItems.Count-1) do begin
        Result := TTagListItem(fItems[idx]);
        if (Result.ItemID = ItemID) then Exit;
      end; {for}
      Result := NIL;
    end;

    function TTagList.Items( Index:integer ):TTagListItem;
    begin
      Result := TTagListItem(fItems[index]);
    end;
    //---------------------------------------------------------
    end.

    0
  • Pomocny post
    #29 08 Gru 2010 15:58
    xanio
    Poziom 27  

    Polecam TObjectList a w nowych Delphi typy generyczne.

    0
  Szukaj w 5mln produktów