Rafraichissement DBGrid

Résolu
cs_Juju1988 Messages postés 70 Date d'inscription jeudi 8 janvier 2009 Statut Membre Dernière intervention 21 juin 2011 - 20 juin 2011 à 14:10
cs_MAURICIO Messages postés 2106 Date d'inscription mardi 10 décembre 2002 Statut Modérateur Dernière intervention 15 décembre 2014 - 22 juin 2011 à 10:12
Bonjour à tous,

J'ai un petit soucis j'ai un DBGrid qui m'affiche des scanners via un OracleDataSet et qui me dessine des cases à cocher cochées ou non via :

// Procédure permettant de dessiner dans les colonnes d'un DBgrid
procedure TMainForm.DBGridScanDrawColumnCell(Sender: TObject;
  const Rect: TRect; DataCol: Integer; Column: TColumn;
  State: TGridDrawState);
begin
  AfficheCaseSav(Rect,Column, DBGridScan, DmImages.imgCheck, DataCol, state);
end;


Voici la procédure :

// Procédure permettant de dessiner les cases à cocher dans la colonne SAV du DBGridScan
procedure AfficheCaseSav(const Rectangle: TRect; maCol : TColumn; monDB : TDBGrid; monJeuDImages : TImageList; colData : Integer; monEtat : TGridDrawState);
begin
if sameText(maCol.FieldName, 'SAV') then
  begin
    { On efface la cellule }
    monDB.Canvas.FillRect(Rectangle);
    { Cochée ou Pas ?}
    monJeuDImages.Draw(monDB.Canvas,
      Rectangle.Left + ((Rectangle.Right - Rectangle.Left - monJeuDImages.Width) div 2),
      Rectangle.Top,
      Ord(monDB.Fields[3].AsString = '0')
    );
  end
  { si column ne correspond pas à une case à cocher, }
  { on ne s'occupe pas du dessin de la cellule, on }
  { transmet donc à DefaultDrawColumnCell }
  else
  begin
    monDB.DefaultDrawColumnCell(Rectangle, colData, maCol, monEtat);
  end;

end;


Cependant j'ai une zone de saisie qui me permet de faire des recherches de scanners cependant quand on commence à écrire cela me dessine toutes mes cases cochées alors qu'elles ne devraient pas l'être... j'ai pourtant mis un refresh je ne comprend pas...

// Permet de faire une recherche de scan
procedure TMainForm.zsRechercheScanChange(Sender: TObject);
begin
  MainForm.OracleDataSetGestionScan.Refresh;
  
  OracleDataSetGestionScan.Close;
  OracleDataSetGestionScan.SQL.Clear;
  OracleDataSetGestionScan.SQL.Add('SELECT * FROM adresseip WHERE nomscan LIKE ''%' + uppercase(zsRechercheScan.Text) +'%''');
  DataSourceGestionScan.DataSet := OracleDataSetGestionScan;
  DBGridScan.DataSource := DataSourceGestionScan;
  OracleDataSetGestionScan.Open;

  MainForm.OracleDataSetGestionScan.Refresh;

end;


Je ne comprend pas...

Merci d'avance pour votre aide

16 réponses

cs_Juju1988 Messages postés 70 Date d'inscription jeudi 8 janvier 2009 Statut Membre Dernière intervention 21 juin 2011
21 juin 2011 à 14:16
J'ai eu une solution qui fonctionne sur un autre forum il faut mettre :

  monJeuDImages.Draw(monDB.Canvas,
      Rectangle.Left + ((Rectangle.Right - Rectangle.Left - monJeuDImages.Width) div 2),
      Rectangle.Top,
      Ord(maCol.Field.AsString = '0')    );


Merci de votre aide !!!
3
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
20 juin 2011 à 15:46
Bonjour,

tente d'encapsuler ta recherche par :

try
"Objet".disablecontrols;

finally
"Objet".Enablecontrols;
end;

et supprime les refresh qui ne servent ici à rien..

cantador
0
cs_Juju1988 Messages postés 70 Date d'inscription jeudi 8 janvier 2009 Statut Membre Dernière intervention 21 juin 2011
20 juin 2011 à 16:02
ça me supprime carrément tout dans mon DBGrid (et dans mon DBGrid seulement...)

// Permet de faire une recherche de scan
procedure TMainForm.zsRechercheScanChange(Sender: TObject);
begin
  //MainForm.OracleDataSetGestionScan.Refresh;

try

    OracleDataSetGestionScan.DisableControls;

  OracleDataSetGestionScan.Close;
  OracleDataSetGestionScan.SQL.Clear;
  OracleDataSetGestionScan.SQL.Add('SELECT * FROM adresseip WHERE nomscan LIKE ''%' + uppercase(zsRechercheScan.Text) +'%''');
  DataSourceGestionScan.DataSet := OracleDataSetGestionScan;
  DBGridScan.DataSource := DataSourceGestionScan;
  OracleDataSetGestionScan.Open;


  finally

    OracleDataSetGestionScan.EnableControls;


end;
0
beckerich Messages postés 302 Date d'inscription jeudi 29 septembre 2005 Statut Membre Dernière intervention 17 septembre 2013 2
20 juin 2011 à 20:26
Bonjour,

juste une petite correction, qui d'ailleurs dans ce contexte ne change rien :

objet.DisableControls;
try
  // traitement
finally
  objet.EnableControls;
end;


Il faut sortir le DisableControls du bloc
try, car si cette ligne échoue, pas besoin du
finally. C'est important dans le cas d'une
allocation de mémoire, par exemple.

toto := TObject.Create;
try
(********************************************
si toto := TObject.Create est fait ici et que
 cela se passe mal, le bloc finally sera 
exécuté, et on tentera de libérer un objet 
non alloué, ce qui provoquera un joli 
RunTimeError ou qque chose dans le genre ;-))
********************************************)
  Caption := toto.ClassName;
finally
  toto.Free;
end


Luc.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_Juju1988 Messages postés 70 Date d'inscription jeudi 8 janvier 2009 Statut Membre Dernière intervention 21 juin 2011
21 juin 2011 à 08:13
Oui c'est ce que j'ai fait après :

procedure TMainForm.zsRechercheScanChange(Sender: TObject);
begin
    OracleDataSetGestionScan.DisableControls;
  try

    OracleDataSetGestionScan.Close;
    OracleDataSetGestionScan.SQL.Clear;
    OracleDataSetGestionScan.SQL.Add('SELECT * FROM adresseip WHERE nomscan LIKE ''%' + uppercase(zsRechercheScan.Text) +'%''');
    DataSourceGestionScan.DataSet := OracleDataSetGestionScan;
    DBGridScan.DataSource := DataSourceGestionScan;
    OracleDataSetGestionScan.Open;
  finally
    OracleDataSetGestionScan.EnableControls;
  end;
end;


Mais j'ai toujours mon problème de rafraichissement... Là ça me vide carrément mon DBGrid...

SVP aidez moi je ne sais plus quoi faire...
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
21 juin 2011 à 09:24
le DisableControls et le EnableControls permettent de désactiver l'affichage d'un objet pendant un traitement.
Cela ne concerne pas la libération d'un objet..

mais mis à part cette précision, cela ne règle pas ton problème..
et je n'ai pas delphi à côté de moi pour tester.

autre chose le OnDrawColumnCell est une procédure évènementielle qui s'active en permanence..et déclencher une recherche pendant l'exécution de cette dernière n'est pas simple..

On pourrait toutefois désactiver l'évènement pendant la recherche,
en le déclarant à nil et le remettre ensuite mais je ne le sens pas du tout.

il doit y avoir une autre solution..

Le mieux serait de décrire exactement ce que tu souhaites réaliser
et là je pense qu'une idée va germer.


cantador
0
cs_Juju1988 Messages postés 70 Date d'inscription jeudi 8 janvier 2009 Statut Membre Dernière intervention 21 juin 2011
21 juin 2011 à 10:19
En fait j'ai une table qui stocke des scanners :
- AdresseIP
- Nom
-...
Et elle stocke aussi s'ils sont en SAV (réparation) si 0 pas en SAV si 1 SAV.
Donc ces scans je les affiche dans un DBGrid et pour la colonne SAV si le scan est en SAV ça m'affiche une case cochée si pas en SAV case non cochée d'où le code :

// Procédure permettant de dessiner les cases à cocher dans la colonne SAV du DBGridScan
procedure AfficheCaseSav(const Rectangle: TRect; maCol : TColumn; monDB : TDBGrid; monJeuDImages : TImageList; colData : Integer; monEtat : TGridDrawState);
begin
// On ne prend en compte que la colonne SAV
if sameText(maCol.FieldName, 'SAV') then
  begin
    { On efface la cellule }
    monDB.Canvas.FillRect(Rectangle);
    { Cochée ou Pas ?}
    monJeuDImages.Draw(monDB.Canvas,
      Rectangle.Left + ((Rectangle.Right - Rectangle.Left - monJeuDImages.Width) div 2),
      Rectangle.Top,
      Ord(monDB.Fields[3].AsString = '0')
    );
  end
  { si column ne correspond pas à une case à cocher, }
  { on ne s'occupe pas du dessin de la cellule, on }
  { transmet donc à DefaultDrawColumnCell }
  else
  begin
    monDB.DefaultDrawColumnCell(Rectangle, colData, maCol, monEtat);
  end;

end;


appelée par :

// Procédure permettant de dessiner dans les colonnes d'un DBgrid
procedure TMainForm.DBGridScanDrawColumnCell(Sender: TObject;
  const Rect: TRect; DataCol: Integer; Column: TColumn;
  State: TGridDrawState);
begin
  AfficheCaseSav(Rect,Column, DBGridScan, DmImages.imgCheck, DataCol, state);
end;


C'est une gestion des scans. Donc par exemple après mon ajout d'un scan je fais un refresh après ma requête pour bien que ce soit pris en compte pareil après un ajout SAV exemple :


// Ajout ou Modif d'un SAV pour un scan donné
procedure TFrmAjoutSAV.btnOkClick(Sender: TObject);
var
  nomDuScan : String;
  nextval : integer;

begin
nomDuScan := '';
nomDuScan := lblNomScan.Caption;

// Ajout d'un SAV
if typeModif = 'Ajout' then
  begin
  oqAjoutSav.Close;
  oqAjoutSav.SQL.Clear;                                                                                             // SEQ_NUMSUIVI permet de récupérer le numéro de suivi suivant relatif à la table SUIVISAV
                                                                                                                   // mais possible grâce à une séquence Oracle SEQ_NUMSUIVI qui s'auto-incrémente
  oqAjoutSav.SQL.Add('INSERT INTO suivisav (numsuivi, numrma, datedepart, dateretour, nomscan, commentaire) VALUES (SEQ_NUMSUIVI.NEXTVAL, :numerorma, :datededepart, :datederetour, :lenomscan, :com)');
  oqAjoutSav.DeclareAndSet('numerorma', otString, uppercase(zsNumRma.Text));
  oqAjoutSav.DeclareAndSet('datededepart', otString, zsDateDep.Text);
  oqAjoutSav.DeclareAndSet('datederetour', otString, zsDateRetour.Text);
  oqAjoutSav.DeclareAndSet('lenomscan', otString, nomDuScan);
  oqAjoutSav.DeclareAndSet('com', otString, zsCommentaires.Text);
  oqAjoutSav.Execute;
  oqAjoutSav.Session.Commit;

  oqMajScan.Close;
  oqMajScan.SQL.Clear;
  oqMajScan.SQL.Add('UPDATE adresseip SET sav 1 WHERE nomscan :nomdescan');
  oqMajScan.DeclareAndSet('nomdescan', otString, nomDuScan);
  oqMajScan.Execute;
  oqMajScan.Session.Commit;

  end
  //Modif d'un SAV, saisie d'une date de retour...
else if typeModif = 'Modif' then
  begin
  oqModifSav.Close;
  oqModifSav.SQL.Clear;
  oqModifSav.SQL.Add('UPDATE suivisav SET numrma :nvrma, datedepart :nvdepart, dateretour = : nvretour, commentaire = :nvcommentaire WHERE nomscan = :nvscan');
  oqModifSav.DeclareAndSet('nvrma', otString, uppercase(zsNumRma.Text));
  oqModifSav.DeclareAndSet('nvdepart', otString, zsDateDep.Text);
  oqModifSav.DeclareAndSet('nvretour', otString, zsDateRetour.Text);
  oqModifSav.DeclareAndSet('nvcommentaire', otString, zsCommentaires.Text);
  oqModifSav.DeclareAndSet('nvscan', otString, nomDuScan);
  oqModifSav.Execute;
  oqModifSav.Session.Commit;

    if (zsDateRetour.Text <> '  /  /    ') and (Trim(zsDateRetour.Text) <> '') then
      begin
      oqMajScan.Close;
      oqMajScan.SQL.Clear;
      oqMajScan.SQL.Add('UPDATE adresseip SET sav 0 WHERE nomscan :nomdescan');
      oqMajScan.DeclareAndSet('nomdescan', otString, nomDuScan);
      oqMajScan.Execute;
      oqMajScan.Session.Commit;
      end;
  end;


  zsNumRma.Text := '';
  zsCommentaires.Text := '';
  zsDateDep.Text := '  /  /    ';
  zsDateRetour.Text := '  /  /    ';

  FrmHistoSav.OracleDataSetHisto.Close;
  FrmHistoSav.OracleDataSetHisto.SQL.Clear;
  FrmHistoSav.OracleDataSetHisto.SQL.Text :'SELECT numsuivi, nomscan, numrma, datedepart, dateretour, commentaire FROM suivisav WHERE nomscan :nomduscan ORDER BY dateretour';
  FrmHistoSav.OracleDataSetHisto.DeclareAndSet('nomduscan', otString, nomDuScan);
  FrmHistoSav.DataSourceHisto.DataSet := FrmHistoSav.OracleDataSetHisto;
  FrmHistoSav.DBGridHisto.DataSource := FrmHistoSav.DataSourceHisto;
  FrmHistoSav.OracleDataSetHisto.Open;

  // On rafraichit l'affichage du DBGrid en rafraichissant le DataSet
  MainForm.OracleDataSetGestionScan.Refresh;
  // Comme ouverture du formulaire en modal on le ferme en modal également de cette façon
  ModalResult := mrOk;

end;




Cependant pour ma zone de saisie qui me permet de faire une recherche sur le nom du scan et d'afficher le résultat en temps réel cela ne fonctionne pas si je commence à taper un nom cela me coche toutes les cases et pareil si après j'efface le texte dans ma zone de recherche. Le refresh ici ne fonctionne pas :

// Permet de faire une recherche de scan dans le DBGrid
procedure TMainForm.zsRechercheScanChange(Sender: TObject);
begin
    OracleDataSetGestionScan.DisableControls;
  try

    OracleDataSetGestionScan.Close;
    OracleDataSetGestionScan.SQL.Clear;
    OracleDataSetGestionScan.SQL.Add('SELECT * FROM adresseip WHERE nomscan LIKE ''%' + uppercase(zsRechercheScan.Text) +'%''');
    DataSourceGestionScan.DataSet := OracleDataSetGestionScan;
    DBGridScan.DataSource := DataSourceGestionScan;
    OracleDataSetGestionScan.Open;
  finally
    OracleDataSetGestionScan.EnableControls;
  end;
end;


Disable et EnableControls me supprime complètement les enregistrements du tableau (d'un point de vue affichage bien sûr).

Voilà je pense que j'ai tout dit ... Si tu as des questions n'hésite pas...
0
beckerich Messages postés 302 Date d'inscription jeudi 29 septembre 2005 Statut Membre Dernière intervention 17 septembre 2013 2
21 juin 2011 à 13:22
bonjour,

@cantador,

merci, je sais bien que Enable/DisableControls n'ont rien à voir avec la libération d'une ressource allouée,
mais le try finally oui...
C'était simplement une petite précision sur l'utilisation d'un tel bloc.

Pour en revenir au problème,

nomDuScan := Uppercase(lblNomScan.Caption);

change-t-il quelque chose ?

Si j'ai bien compris, sans le bloc Enable/Disable, le dbgrid affiche les données, pas comme il faut mais
il les affiche ?
Crées-tu les colonnes du dbgrid en design ou en runtime ? C'est peut-être aussi une piste à essayer.
J'essaye qque chose chez moi et je reviens.

Luc.
0
cs_Juju1988 Messages postés 70 Date d'inscription jeudi 8 janvier 2009 Statut Membre Dernière intervention 21 juin 2011
21 juin 2011 à 13:36
Uppercase ne change rien...
Oui il affiche les données. Mais me met pas le bon dessin de cases il me met des cases à cocher au lieu de cases vides.
Les colonnes du DBgrid sont crées dynamiquement par ma requête d'affichage...
0
beckerich Messages postés 302 Date d'inscription jeudi 29 septembre 2005 Statut Membre Dernière intervention 17 septembre 2013 2
21 juin 2011 à 14:04
Re,

j'ai testé ce code chez moi sur Delphi 7 et base Informix, il fonctionne (table de 150000 records) :

procedure TFM_MAIN.SED_CAT1Change(Sender: TObject);
begin
  with IfxQuery1 do
  begin
    DisableControls;
    try
      Close;
      SQL.Clear;
      SQL.Add('select * from lal_ini where cleini like ''%' + SED_CAT1.Text + '%''');
      Open;
    finally
      EnableControls;
    end;
  end;
end;

procedure TFM_MAIN.AfficheCaseSav(const Rectangle: TRect; maCol: TColumn;
  monDB: TDBGrid; monJeuDImages: TImageList; colData: Integer;
  monEtat: TGridDrawState);
begin
  if monDB.Datasource.DataSet.FieldByName('VALPAR').AsString = '1' then
  begin
    { On efface la cellule }
    monDB.Canvas.FillRect(Rectangle);
    { Cochée ou Pas ?}
    monJeuDImages.Draw(monDB.Canvas,
      Rectangle.Left + ((Rectangle.Right - Rectangle.Left - monJeuDImages.Width) div 2),
      Rectangle.Top, 2);
  end
  { si column ne correspond pas à une case à cocher, }
  { on ne s'occupe pas du dessin de la cellule, on }
  { transmet donc à DefaultDrawColumnCell }
  else
  begin
    monDB.DefaultDrawColumnCell(Rectangle, colData, maCol, monEtat);
  end;
end;

procedure TFM_MAIN.DBGrid1DrawColumnCell(Sender: TObject;
  const Rect: TRect; DataCol: Integer; Column: TColumn;
  State: TGridDrawState);
begin
  AfficheCaseSav(Rect, Column, DBGrid1, ImageList1, 2, State);  
end;



Je n'ai pas d'idée pour le moment. Désolé,
Luc.
0
beckerich Messages postés 302 Date d'inscription jeudi 29 septembre 2005 Statut Membre Dernière intervention 17 septembre 2013 2
21 juin 2011 à 14:07
Ord(monDB.Fields[3].AsString = '0');


si '0' donne True donc ImageIndex=1
si <> '0' donne False donc ImageIndex=0

les images du ImageList sont à la bonne place ?

Luc.
0
cs_Juju1988 Messages postés 70 Date d'inscription jeudi 8 janvier 2009 Statut Membre Dernière intervention 21 juin 2011
21 juin 2011 à 14:17
Oui sinon les images dans bien dans l'imageList
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
21 juin 2011 à 14:17
Bonjour,

@beckerich :
toto := TObject.Create;
tu raisonnes comme si un objet était en création..
mais ici, il n'y en a pas et dans ce cas cette écriture ne pose pas de souci.
Effectivement, s'il y en avait un, ce serait une erreur d'écriture..
il faut simplement adapter..

@Juju1988 :
si je commence à taper un nom cela me coche toutes les cases

Oui, c'est normal..
toutes les procédures se déclenchent en même temps sans aucun contrôle..

ça veut dire que la méthode n'est pas correcte et qu'il faut revoir le concept..

il ne faut pas hésiter à tout refaire dans un autre environnement :
ex : changer de système d'affichage :
StringGrid, drawGrid, ListView etc..
jouer aussi sur la couleur..

le TDbgrid est rapide et léger, mais pauvre en affichage..
(avec un TcxGrid, la solution serait vite trouvée..car tout pourrait être réalisé en dynamique)

cantador
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
21 juin 2011 à 14:21
@Juju1988 :

posts croisés..

content que tu es trouvé quelque chose


cantador
0
cs_Juju1988 Messages postés 70 Date d'inscription jeudi 8 janvier 2009 Statut Membre Dernière intervention 21 juin 2011
21 juin 2011 à 14:24
Vouiiiii moi aussi merci de ton aide :)
0
cs_MAURICIO Messages postés 2106 Date d'inscription mardi 10 décembre 2002 Statut Modérateur Dernière intervention 15 décembre 2014 5
22 juin 2011 à 10:12
Solution: tcyDBGrid ou tcyDBAdvGrid de mon pack de compos qui gèrent déjà le checkbox ici, télécharge aussi la démo :
Composants Cindy pour Delphi

A+
0
Rejoignez-nous