IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Voir le flux RSS

Blog de Serge Girard (aka SergioMaster)

[Dephi][VCL]Carnet de plongées : TControlList, Jour 2 - Entrainement piscine

Noter ce billet
par , 11/03/2021 à 15h26 (1092 Affichages)
Ce billet fait suite à :
La découverte (snorkling)
Apnée
Première plongée

Aujourd'hui, pas de sortie en mer pour voir des poissons, un petit entrainement en piscine avec du matériel pro. On ne se refait pas, quand je vois ça d'accroché je ne peux pas ne pas revenir à mon ancienne profession.

Nom : sortinager_small.PNG
Affichages : 730
Taille : 59,2 Ko

En guise de piscine : votre disque dur. L'objectif, faire une sorte de browser d'images.

Comment va être composé notre interface utilisateur ?
Il va nous falloir de quoi sélectionner un répertoire, la possibilité d'avoir une liste des fichiers images et bien sûr le TControlList qui contiendra le nom du fichier et l'image réduite.

Nom : Capture.PNG
Affichages : 130
Taille : 35,5 Ko

Je vous laisse vous équiper (reproduire le design) pour cette partie.

On commencera doucement par la fonctionnalité qui est de cacher ou montrer la liste : utilisation de l'évènement OnClick du CheckBox
Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
Memo1.Visible:=CheckBox1.Checked;
end;

Premier gros oeuvre, sélectionner un répertoire. La VCL ne nous fourni pas de composant visuel pour le faire, par contre dans la VCL existe une fonction SelectDirectory qui va être parfaitement adaptée au besoin. J'en utiliserai sa seconde forme function SelectDirectory(const Caption: string; const Root: WideString; var Directory: string; Options: TSelectDirExtOpts; Parent: TWinControl): Boolean;
Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  dir: String;
begin
  if SelectDirectory('Choisissez le répertoire', '', dir,
    [sdshowEdit, sdShowShares, sdShowFiles], self) then
  begin
    edtDir.Text := dir;
    // c'est ici que nous récupérerons la liste de nos images, place du "CODE PRINCIPAL" 
  end;
Première mise en place du chantier, une récupération des fichiers png existant dans le répertoire sélectionner.
Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    
   // CODE PRINCIPAL  
   ControlList1.Enabled := False; // désactiver le TControlList
    // récupérer la liste des fichiers images
    FileList := TDirectory.GetFiles(dir, '*.png'); // uniquement les png  TDirectory est contenu dans l'unité System.IOUtils à déclarer dans la liste des uses
    if Memo1.Visible then
    begin
      Memo1.Lines.Clear;
      for var s: String in FileList do
        Memo1.Lines.Add(ExtractFileName(s));
    end;
    // indiquer le nombre d'éléments que contiendra la liste
    ControlList1.ItemCount := Length(FileList);
    // activer la liste (ce qui lancera le onBeforeDrawItem)
    ControlList1.Enabled := True;
Comme cette liste sera utilisée dans au moins deux fonctions, il faut déclarer une variable FileList de type TArray<String> dans la partie privée de la forme.
Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
  private
    { Déclarations privées }
    FileList: TArray<String>;

on n'oublie pas, bien sûr, ce que l'on a appris dans les billets précédents et l'on précode l'évènement OnDrawItem du TControlList.
Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
procedure TForm1.ControlList1BeforeDrawItem(AIndex: Integer; ACanvas: TCanvas;
  ARect: TRect; AState: TOwnerDrawState);
begin
  LblBrowser.Caption := TPath.GetFileNameWithoutExtension(FileList[AIndex]);
  imgBrowser.Picture.LoadFromFile(FileList[AIndex]);
end;

Nom : Capture_2.PNG
Affichages : 147
Taille : 318,3 Ko

Pas mal pour un premier résultat mais, lors de la sélection de tailles plus faibles, l'eau serait-elle trouble ? Non, il s'agit d'un crénelage dû au Stretch de la propriété du TImage.

Comment éviter ça ? Comme solution je me propose de récupérer la taille de l'image et, fonction de celle-ci changer la propriété Stretch.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
procedure TForm1.ControlList1BeforeDrawItem(AIndex: Integer; ACanvas: TCanvas;
  ARect: TRect; AState: TOwnerDrawState);
begin
  if Length(FileList) = 0 then exit; // par précaution
  LblBrowser.Caption := TPath.GetFileNameWithoutExtension(FileList[AIndex]);

  // un peu plus q'un simple Stretch pour l'image ?
  // obtenir les informations fichier
  var vImage: Timage := TImage.Create(self);
   try
      vImage.AutoSize := True;
      vImage.Picture.LoadFromFile(FileList[AIndex]);
      imgBrowser.Stretch := (vImage.Height > imgBrowser.Height) OR (vImage.Width > imgBrowser.Width);
      imgBrowser.AutoSize:=not imgBrowser.Stretch;
      imgBrowser.Center:=not imgBrowser.Stretch;
      imgBrowser.Picture.LoadFromFile(FileList[AIndex]);
  finally
    vImage.Free;
  end;
end;
Nom : Capture_3.PNG
Affichages : 147
Taille : 28,6 Ko

Du coup, 16x16 c'est un peu petit. Il faudrait certainement améliorer ça mais je préfére passer à un autre stade : Ne pas en rester uniquement aux png mais montrer tout types d'images (du moins les plus courantes, bmp,png,jpg,jpeg,ico). Premier écueil ( dans une piscine !) la fonctionTDirectory.GetFiles ne permet pas, dans son argument SearchPattern, de mettre plus d'un masque, il va falloir utiliser une de ses autres formes permettant l'ajout d'une fonction de type TFilterPredicate.
Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
function aFilter(const Path: string; const SearchRec: TSearchRec): Boolean;
// TFilterPredicate
const
  extensions = '.png,.jpg,.jpeg,.bmp,.ico'; // extensions voulues
begin
  result := extensions.Contains(ExtractFileExt(SearchRec.Name));
end;
Utilisation FileList := TDirectory.GetFiles(dir, '*.*',aFilter); ou, en mode plus expert, en utilisant une méthode anonyme.
Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
 
FileList := TDirectory.GetFiles(dir, '*.*',
      function(const Path: string; const SearchRec: TSearchRec): Boolean
      const
        extensions = '.png,.jpg,.jpeg,.bmp,.ico'; // extensions voulues
      begin
        result := extensions.Contains(ExtractFileExt(SearchRec.Name));
      end);

Citation Envoyé par Erreur
Extension de fichier image inconnue (.jpg)
Petit incident de plongée. Pas de panique, il suffit d'ajouter dans la listes des uses l'unité VCL.Imaging.jpeg, cela aurait déjà pu se produire avec les fichiers .png mais, par chance l'utilisation de l'unité VCL.Imaging.pngimage était, elle, déclarée certainement lors du design, une chance .

Nom : Capture_5.PNG
Affichages : 126
Taille : 243,9 Ko
Un peu de débriefing pour clore l'exercice :
  1. L'utilisation des jpg ralenti considérablement le programme. Un passage par des vignettes pourrait être la solution.
  2. Certaines icones (.ico), s'affichent mal, une question de tailles mal récupérées.
  3. L'API SelectDirectory coince un peu aux entournures, le dernier répertoire utilisé, ce qui serait pratique, n'est pas mémorisé.

Envoyer le billet « [Dephi][VCL]Carnet de plongées : TControlList, Jour 2 - Entrainement piscine » dans le blog Viadeo Envoyer le billet « [Dephi][VCL]Carnet de plongées : TControlList, Jour 2 - Entrainement piscine » dans le blog Twitter Envoyer le billet « [Dephi][VCL]Carnet de plongées : TControlList, Jour 2 - Entrainement piscine » dans le blog Google Envoyer le billet « [Dephi][VCL]Carnet de plongées : TControlList, Jour 2 - Entrainement piscine » dans le blog Facebook Envoyer le billet « [Dephi][VCL]Carnet de plongées : TControlList, Jour 2 - Entrainement piscine » dans le blog Digg Envoyer le billet « [Dephi][VCL]Carnet de plongées : TControlList, Jour 2 - Entrainement piscine » dans le blog Delicious Envoyer le billet « [Dephi][VCL]Carnet de plongées : TControlList, Jour 2 - Entrainement piscine » dans le blog MySpace Envoyer le billet « [Dephi][VCL]Carnet de plongées : TControlList, Jour 2 - Entrainement piscine » dans le blog Yahoo

Catégories
Programmation , Delphi

Commentaires