Results 1 to 13 of 13

Thread: afbeelding veranderen in DBImage

  1. #1
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747

    afbeelding veranderen in DBImage

    Als ik al een afbeelding in DBimage heb staan en ik wil daar een andere afbeelding voor in de plaatst, zie ik dat de nieuwe over de oude gaat. Gezocht met google af gaf mij aan om picture := nil toe te voegen.
    Delphi Code:
    1. procedure tPokemon.FotoToBlobfield(aDBImage: TDBImage);
    2. var BlobField: TBlobField;
    3. begin
    4.   with TOpenPictureDialog.Create(nil) do
    5.   begin
    6.     try
    7.       if Execute then
    8.       begin
    9.         if aDBImage.Picture <> nil then
    10.           aDBImage.Picture := nil;
    11.         if fCurrentdataset.State in [dsBrowse] then
    12.           fCurrentdataset.Edit;
    13.         BlobField := fCurrentdataset.FieldByName('afbeelding') as TBlobField;
    14.         BlobField.LoadFromFile(FileName);
    15.       end;
    16.     finally
    17.       Free;
    18.     end;
    19.   end;
    20. end;
    Dat werkt niet. Ook niet als ik de ik de if aDBImage.Picture regel weglaat. Iemand suggesties om DBImage leeg te maken?
    Delphi is great. Lazarus is more powerfull

  2. #2
    Senior Member ErikB's Avatar
    Join Date
    Aug 2010
    Location
    Biddinghuizen
    Posts
    509
    wat bij mij werkt:

    Code:
       
     tblklant.Edit;
     tblKlant.FieldByName('foto').Clear;
    daarna zou je de nieuwe afbeelding er weer in kunnen zetten

    Edit: Dit zou wel eens een aparte functie van DBIsam kunnen zijn ...
    Erik

  3. #3
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,708
    Volgens mij moet je gewoon:
    • Dataset op DisableControls
    • Dataset edit
    • Nieuwe blob laden in de dataset
    • Dataset posten
    • Als laatste de dataset weer enablen met EnableControls
    TMemoryLeak.Create(Nil);

  4. #4
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    Dat doe dus ook gewoon, Peter. Maar ik zie gewoon dat over de oude afbeelding een nieuwe wordt geplaatst. Dan zijn het er ineens 2 voor de prijs van 1. Toch iets teveel van het goede.

    @ErikB
    Ga proberen of dat werkt.
    Delphi is great. Lazarus is more powerfull

  5. #5
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,708
    Ah, dan zit er gewoon een bugje in de VCL-control zelf.
    De oplossing van Erik maakt alleen het veld leeg vrees ik, dus dan moet je de TDBImage
    geforceerd laten hertekenen (en dan zou je inderdaad denken aan een picture := nil en
    daarna een invalidate oid).
    TMemoryLeak.Create(Nil);

  6. #6
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    Daar ben ik ook bang voor
    Delphi is great. Lazarus is more powerfull

  7. #7
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    Het probleem zit niet in het veranderen van een afbeelding in de database, maar in de DBImage zelf. Deze maakt TImage.picture niet goed leeg, waardoor er een afbeelding over de oude wordt geplaatst. TjvDBImage werkt wel goed, maar die wil ik niet gebruiken (wil eigenlijk van Jedi af). Om te kijken hoe deze component het doet is zoeken 'naar een naald in een hooiberg'.
    Ik heb vervolgens een tImage op mijn form geplaatst en een OnAfterscroll geplaatst, die de afbeelding laat vanuit de database en deze op het scherm toont. Dat werkt goed (zelfs veel netter zonder die kader erom heen).
    Om TDBImage.picture = nil te forceren, heb ik zelfs een OnBeforescroll geplaatst om TPicure echt leeg te maken. Maar dat mag niet baten.
    Delphi is great. Lazarus is more powerfull

  8. #8
    waar haal jij je filename vandaan?

    Wat ik niet snap is dat je adbimage meegeeft als parameter en vervolgens de picture leeg maakt. Verder vraag ik me af waarom je een gui component gebruikt om een database veld te updaten.

  9. #9
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    Dat doe ik ook niet.
    Database wordt onafhankelijk gevuld in die procedure staat niet in de form. Die parameter heb ik later toegevoegd om zeker te weten dat het scherm 'schoon' wordt gemaakt. Maar ik heb gemerkt dat het probleem niet in het laden van de afbeelding naar de database is, maar het tonen er van.

    Filename komt van TPicturedialog vandaan.
    Delphi is great. Lazarus is more powerfull

  10. #10
    Sowieso mag je niets met de TDBImage doen als die nog connected is aan een TField. Dus TDBImage.Picture := nil is eigenlijk uit den boze want de image moet uit de database komen en met := nil ga je zelf lopen klungelen aan een dataware component.

    Als je al TDBImage.Picture.Assign(nil); of TDBImage.Picture := nil; doet, zorg er dan wel voor dat je dataset al in .Edit staat !!
    (want in jouw gegeven voorbeeld is dat niet het geval. De dataset zet je "te laat" in Edit.)

    Wat je e.v. wel zou kunnen doen is de connectie los te koppelen.
    Dus... TDBImage.DataField := nil in de OnBeforeScroll en TDBImage.DataField := Field in de OnAfterScroll.

    Dit zou je ook kunnen proberen voor het laden.

  11. #11
    En natuurlijk een bug melden.

    Het update mechanisme is tamelijk simpel. Met een DataLink zit je data-aware control gekoppeld aan de datasource. Net als een TDBEdit zou ook een TDBImage direct updates moeten krijgen. Die update zou simpelweg de nieuwe veldwaarde moeten zijn. Je laadt een hele nieuwe file in het blobfield, en zoals je al zei is de waarde in de database ook goed. Dat betekent dus dat TDBImage iets geks doet met de afbeelding. Mogelijk probeert hij de image te schalen en tekent hij 'm daarvoor op een zelf-gemanaged canvas dat niet goed geleegd wordt.

    Het grappige (?) is dat TDBImage helemaal niet afgeleid is van TImage. Het is afgeleid van TCustomControl, en wellicht is er in de (her)implementatie van het gedrag van de image dus iets verkeerd gegaan.

    Ik zit in de implementatie van TDBImage.Paint te kijken, en daar gebeurt wel wat interessants. Eerst wordt de afbeelding getekend, en daarna wordt, afhankelijk van de properties Stretch en Proportional de buitenrand eraf geknipt. Waarom dat zo is gedaan weet ik niet, maar wellicht gaat daarmee iets verkeerd? Er is in ieder geval (in de VCL van Delphi 10, Berlin) wel rekening gehouden met de mogelijkheid van afbeeldingen met verschillende grootte.
    1+1=b

  12. #12
    Net even een testje geprobeerd te maken, maar deze regel geeft bij mij al een fout "Bitmap image is not valid". Krijg jij dat niet?

    Delphi Code:
    1. BlobField.LoadFromFile(FileName);
    Last edited by GolezTrol; 23-Apr-18 at 13:52.
    1+1=b

  13. #13
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    Dit is uiteindelijk de class, die ik gemaakt heb.
    Delphi Code:
    1. unit clPokemon;
    2.  
    3. interface
    4.  
    5. uses system.classes, system.sysutils, system.variants,  data.db, vcl.stdctrls,
    6.      Vcl.Dialogs, Vcl.ExtDlgs, dModule, vcl.dbCtrls, vcl.imaging.pngimage,
    7.      clBasis, vcl.extctrls;
    8.  
    9. type tPokemon = class(tBasis)
    10.     fImage  : TImage;
    11.   private
    12.   public
    13.     procedure FotoToBlobfield;
    14.     procedure ShowPicture;
    15.     procedure init(aDs: TDatasource;aImage: TImage);
    16.     procedure DoAfterScroll(dataset : tdataset);
    17.  
    18.     destructor Destroy; override;
    19. end;
    20.  
    21. implementation
    22.  
    23. { tPokemon }
    24.  
    25. destructor tPokemon.Destroy;
    26. begin
    27.   fCurrentdataset.active := false;
    28.   inherited;
    29. end;
    30.  
    31. procedure tPokemon.init(aDs: TDatasource;aImage: TImage);
    32. begin
    33.   fImage := aImage;
    34.   fCurrentdataset := DMModule.pokemons;
    35.   aDs.DataSet := fCurrentdataset;
    36.   fCurrentdataset.Active := true;
    37.   DMModule.pokemons.AfterScroll := DoAfterScroll;
    38. end;
    39.  
    40. procedure tPokemon.DoAfterScroll(dataset: tdataset);
    41. begin
    42.   ShowPicture
    43. end;
    44.  
    45. procedure tPokemon.ShowPicture;
    46. var BlobStream: TStream;
    47. begin
    48.   fImage.Picture := nil;
    49.   BlobStream := TMemoryStream.Create;
    50.   try
    51.     if not DMModule.pokemons.FieldByName('afbeelding').IsNull then
    52.     begin
    53.       DMModule.pokemons.GetBlob(DMModule.pokemons.FieldByName('afbeelding')).SaveToStream(BlobStream);
    54.       Blobstream.Position := 0;
    55.       fImage.Picture.loadfromstream(blobstream);
    56.     end;
    57.   finally
    58.     BlobStream.Free;
    59.   end;
    60.  
    61. end;
    62.  
    63. procedure tPokemon.FotoToBlobfield;
    64. var BlobField: TBlobField;
    65. begin
    66.   with TOpenPictureDialog.Create(nil) do
    67.   begin
    68.     try
    69.       if Execute then
    70.       begin
    71.         if fCurrentdataset.State in [dsBrowse] then
    72.           fCurrentdataset.Edit;
    73.         BlobField := fCurrentdataset.FieldByName('afbeelding') as TBlobField;
    74.         BlobField.LoadFromFile(FileName);
    75.       end;
    76.     finally
    77.       Free;
    78.     end;
    79.   end;
    80. end;
    Het werkt beter dan ik had verwacht.

    Ja, ik zal het moeten aanmelden als bug. Maar nooit gedaan bij embarcadero en volgens mij best wel arbeidsintensief (maar anders wordt het nooit aangemeld). Maar voordat dat is opgelost, zal ik toch verder moeten en is mijn oplssing op dit moment het beste wat ik kan verzinnen.
    Delphi is great. Lazarus is more powerfull

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •