Problem with the TPictureList

Hi,

   I created a class(TUrunKartiClass)  with TPictureList. But when i load pictures to TPictureList class and then try to use it in a function i get an access violation error as described in the code.  When i run through the code i get an access violaiton error here : myPicture.Graphic.SaveToStream(TempStream);
   What is wrong with this.
   Thanks in advance.



//THIS IS THE CLASS I HAVE CREATED.

unit UrunKartiClass;

interface

uses  Graphics, Contnrs, Classes;

type
     TPictureList = Class(TObjectList)
         protected
            procedure SetResim(I: Integer; APicture: TPicture);
            function GetResim(I: Integer): TPicture;
         public
            function Add(APicture: TPicture): Integer;
            property Items[I: Integer]: TPicture read GetResim write SetResim;

     End;

   TUrunKartiClass = class
         private
            UrunKodu         : String;
            UrunAdi          : String;
            UrunGrubu        : String;
            Birimi           : String;
            UrunBoyutlari    : String;
            Aciklama         : String;
            EnSonKayitTarihi : String;

         published

         public
                UrunResimleriList :  TPictureList;

                Constructor   Create(
                      pUrunKodu         : String;
                      pUrunAdi          : String;
                      pUrunGrubu        : String;
                      pBirimi           : String;
                      pUrunBoyutlari    : String;
                      pAciklama         : String
                   );Overload;

                Constructor Create(pUrunKodu : String); Overload;

                Function  Kaydet : Boolean;
                Function  UrunResimleriniKaydet( pUrunResimleri : array of TPicture) : Boolean;
                Function  UrunKartiKayitliMi : Boolean;

   end;



implementation

uses DatabaseBaglantisi, MSAccess, General, Sysutils, Windows,  DB;



Procedure TPictureList.SetResim(I : Integer; APicture : TPicture) ;
begin
  inherited Put(I, APicture);
end;

Function TPictureList.GetResim(I : Integer) : TPicture ;
begin
     Result := TPicture(inherited Get(I));
end;

Function TPictureList.Add(APicture : TPicture) : Integer ;
begin
     Result := inherited Add(APicture);
end;


Constructor TUrunKartiClass.Create(
      pUrunKodu         : String;
      pUrunAdi          : String;
      pUrunGrubu        : String;
      pBirimi           : String;
      pUrunBoyutlari    : String;
      pAciklama         : String);
begin
    UrunKodu           := pUrunKodu;
    UrunAdi            := pUrunAdi;
    UrunGrubu          := pUrunGrubu;
    UrunBoyutlari      := pUrunBoyutlari;
    Aciklama           := pAciklama;
end;

Constructor TUrunKartiClass.Create(pUrunKodu : String);
begin
    //BU CONSTRUCTOR ILE DATABASE DEN KAYIT BULUNUP OBJECT E ATANACAK.
end;

Function  TUrunKartiClass.Kaydet : Boolean;
var TempQuery : TMSQuery;
    i : Integer;
    TempStream : TMemoryStream;
    myPicture : TPicture;
begin
    //DEFAULT OLARAK KAYDETMEDI OLARAK VARSAYALIM.
    Result := False;
    if ConnectToDB then
    begin
        try
           Mouse_Bekleme;
           DBConnection.StartTransaction;
           //INSERTS UPDATES DELETES COME HERE
           try
             TempQuery := TMSQuery.Create(TempQuery);
             TempQuery.Connection := DBConnection;
             TempQuery.SQL.Clear;
             TempQuery.Params.Clear;
             TempQuery.SQL.Text := 'Insert into Tab_Urun_Kartlari Values(' +
                                   ':ProjeGrubu, :ProjeKodu, :UrunKodu, :UrunAdi, :UrunGrubu, :Birimi, ' +
                                   ':UrunBoyutlari, :Aciklama, :EnSonKayitTarihi ' +
                                   ')';
             TempQuery.ParamByName('ProjeGrubu').AsInteger      := 1;
             TempQuery.ParamByName('ProjeKodu').AsInteger       := 1;
             TempQuery.ParamByName('UrunKodu').AsString         := Trim(UrunKodu);
             TempQuery.ParamByName('UrunAdi').AsString          := Trim(UrunAdi);
             TempQuery.ParamByName('UrunGrubu').AsString        := Trim(UrunGrubu);
             TempQuery.ParamByName('Birimi').AsString           := Trim(Birimi);
             TempQuery.ParamByName('UrunBoyutlari').AsString    := Trim(UrunBoyutlari);
             TempQuery.ParamByName('Aciklama').AsString         := Trim(Aciklama);
             TempQuery.ParamByName('EnSonKayitTarihi').AsString := EnSonKayitTarihi;
             TempQuery.Execute;

             MesajGoster(IntToStr(UrunResimleriList.Count), mb_ok);
             for i := 0 to  UrunResimleriList.Count - 1 do
             begin
                 TempQuery.SQL.Clear;
                 TempQuery.Params.Clear;
                 TempQuery.SQL.Text := 'Insert into Tab_Urun_Resimleri Values(' +
                                       ':ProjeGrubu, :ProjeKodu, :UrunKodu, :ResimID, :UrunResmi ' +
                                       ')';
                 TempQuery.ParamByName('ProjeGrubu').AsInteger      := 1;
                 TempQuery.ParamByName('ProjeKodu').AsInteger       := 1;
                 TempQuery.ParamByName('UrunKodu').AsString         := Trim(UrunKodu);
                 TempQuery.ParamByName('ResimID').AsInteger         := i + 1;
                 try
                   //SIMDI ÜRÜN RESIMLERINI KAYDEDELIM.
                   TempStream := TMemoryStream.create;
                   TempStream.Position := 0;
                   myPicture := TPicture.Create;
                   myPicture := UrunResimleriList.GetResim(i);
                   MesajGoster(IntToStr(i), mb_ok);
                   //*************I GET ACCESS VIOLATION ERROR HERE**********
                   myPicture.Graphic.SaveToStream(TempStream);
                   TempQuery.ParamByName('UrunResmi').LoadFromStream(TempStream,ftBlob);
                   TempQuery.Execute;
                 finally
                   TempStream.Free;
                   FreeAndNil(myPicture);
                 end;
             end;
           finally
             TempQuery.Free;
           end;
           DBConnection.Commit;
           Result := True;
           Mouse_Normal;
           KaydedildiMesajiGoster;
        Except
         on E : Exception do
         begin
           DBConnection.Rollback;
           Mouse_Normal;
           KaydedilemediMesajiGoster;
           MesajGoster2('HATA OLUSTU. LÜTFEN HATAYI NOT ALIP BILGI ISLEME BILDIRINIZ. HATA AÇIKLAMASI = '+E.Message, mb_ok);
           Result := False;
         end;
        end;
        DisconnectFromDB;
    end else Result := False;
end;


Function  TUrunKartiClass.UrunResimleriniKaydet( pUrunResimleri : array of TPicture) : Boolean;
begin



end;


Function  TUrunKartiClass.UrunKartiKayitliMi() : Boolean;
begin

end;

end.





// I USE ABOVE CLASS HERE

procedure TfrmUrunTanimlama.btnKaydetClick(Sender: TObject);
var
    TempStream: TMemoryStream;
    i : Integer;
    TempUrunKarti : TUrunKartiClass;
    myPicture : TPicture;
begin
     TempUrunKarti := TUrunKartiClass.Create(
                                              Trim(txtUrunKodu.Text),
                                              Trim(txtUrunAdi.Text),
                                              Trim(txtUrunGrubu.Text),
                                              Trim(comboBirimi.Text),
                                              Trim(txtUrunBoyutlari.Text),
                                              Trim(memoAciklama.Lines.Text)
                                            );

     TempUrunKarti.UrunResimleriList := TPictureList.Create(True);

     for i := 0 to  cxGrid1View1.DataController.RecordCount - 1 do
     begin
         try
           TempStream := TMemoryStream.Create;
           TempStream.Position := 0;
           myPicture  := TPicture.Create;
           cxImage.LoadPicture(myPicture, cxImage.GetGraphicClassByName('TJPEGImage'), cxGrid1View1.DataController.Values[i,cxGrid1View1UrunResimleri.Index]);
           myPicture.Graphic.SaveToStream(TempStream);
           TempUrunKarti.UrunResimleriList.Add(myPicture);
         Finally
           TempStream.Free;
//           objPicture.Free;
           FreeAndNil(myPicture);
         end;
     end;
     MesajGoster(Inttostr(TempUrunKarti.UrunResimleriList.Count), mb_ok);

     TempUrunKarti.Kaydet;


     TempUrunKarti.Free;
end;

Open in new window

mhanefitelAsked:
Who is Participating?
 
Emmanuel PASQUIERFreelance Project ManagerCommented:
there are a few errors, design mistakes, and a lot of things I don't understand.

instead of having you list in public in TUrunKartClass, it better be private, created and freed by the parent class instead of created/freed manually by the event that use the class.

also, you have to constructors, why not, but they are not complete. Supposing one is not published here but is doing a lot of things, the other should call the first. Or better yet, use only one constructor but with default values (empty strings) for unused parameters
You'll need a destructor as well.

In Kaydet method, you are creating a TPicture and assigning it to one of the list, that is an error. You should not create it first
//                   myPicture := TPicture.Create;  // remove this line
                   myPicture := UrunResimleriList[i]; // use it with the default property
and you should not destroy it after, because it's owned by the list, so a second run through th elist will only cause you troubles (access violations)
                 finally
                   TempStream.Free;
//                   FreeAndNil(myPicture); // don't free objects owned by a TObjectList
                 end;

in btnKaydetClick, you don't us your temp stream therefore don't need it at all.

In TPictureList , you don't need to redefine Add, as it is already the same in TObjectList with a minor detail of
  TPictureList = Class(TObjectList)
   protected
    procedure SetResim(I: Integer; APicture: TPicture);
    function GetResim(I: Integer): TPicture;
   public
    property Items[I: Integer]: TPicture read GetResim write SetResim; default; // set it the default array property
  End;

  TUrunKartiClass = class
   private
    UrunKodu         : String;
    UrunAdi          : String;
    UrunGrubu        : String;
    Birimi           : String;
    UrunBoyutlari    : String;
    Aciklama         : String;
    EnSonKayitTarihi : String;
    UrunResimleriList :  TPictureList;
   published
   public
    Constructor   Create(
                      pUrunKodu         : String;
                      pUrunAdi          : String;
                      pUrunGrubu        : String;
                      pBirimi           : String;
                      pUrunBoyutlari    : String;
                      pAciklama         : String
                   );Overload;
    Constructor Create(pUrunKodu : String); Overload;
    Destructor Destroy; override;

    procedure AddPicture(P:TPicture);

    Function  Kaydet : Boolean;
    Function  UrunResimleriniKaydet( pUrunResimleri : array of TPicture) : Boolean;
    Function  UrunKartiKayitliMi : Boolean;
   end;


Constructor TUrunKartiClass.Create(
      pUrunKodu         : String;
      pUrunAdi          : String;
      pUrunGrubu        : String;
      pBirimi           : String;
      pUrunBoyutlari    : String;
      pAciklama         : String);
begin
    Create(pUrunKodu); // calling other constructor
    UrunAdi            := pUrunAdi;
    UrunGrubu          := pUrunGrubu;
    UrunBoyutlari      := pUrunBoyutlari;
    Aciklama           := pAciklama;
end;

Constructor TUrunKartiClass.Create(pUrunKodu : String);
begin
 // do lots of things
 // and create the list
 UrunResimleriList := TPictureList.Create(True);
end;

Destructor TUrunKartiClass.Destroy;
begin
 UrunResimleriList.Free;
 inherited;
end;

procedure TUrunKartiClass.AddPicture(P:TPicture);
begin
 UrunResimleriList.Add(P);
end;


procedure TfrmUrunTanimlama.btnKaydetClick(Sender: TObject);
var
  i : Integer;
  TempUrunKarti : TUrunKartiClass;
  myPicture : TPicture;
begin
 TempUrunKarti := TUrunKartiClass.Create(
  Trim(txtUrunKodu.Text),Trim(txtUrunAdi.Text),
  Trim(txtUrunGrubu.Text),Trim(comboBirimi.Text),
  Trim(txtUrunBoyutlari.Text),Trim(memoAciklama.Lines.Text) );

 for i := 0 to  cxGrid1View1.DataController.RecordCount - 1 do
  try
    myPicture  := TPicture.Create; // I'm not sure you should create it first. I don't know TcxImage, so I can't tell. Try commenting this line, and if it works, then it is a mistake to create it first
    cxImage.LoadPicture(myPicture, 
        cxImage.GetGraphicClassByName('TJPEGImage'),
cxGrid1View1.DataController.Values[i,cxGrid1View1UrunResimleri.Index]);
    TempUrunKarti.AddPicture(myPicture);
  Finally
//   FreeAndNil(myPicture); don't free it as it is owned by the list
  end;
  TempUrunKarti.Kaydet;
  TempUrunKarti.Free;
end;

Open in new window

0
 
Emmanuel PASQUIERFreelance Project ManagerCommented:
I didn't finished my comment after correcting the code.
Your biggest errors are that you are creating objects before assigning the variables to others instance in  lists. Therefore you are leaking memory. And worse, you destroy those instance while they are still stored in the list. When you try to access to the objects in the list again after that, the memory zone they are pointing to have been released which cause the access violations.
0
 
mhanefitelAuthor Commented:
Thanks. I made corrections as you said.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.