Miniatures d'images dans un scrollbox

Résolu
cs_saravana Messages postés 91 Date d'inscription vendredi 25 mars 2005 Statut Membre Dernière intervention 18 octobre 2007 - 29 mars 2006 à 18:39
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 - 3 avril 2006 à 15:52
bonjour a tous
je suis en train de réaliser une visionneuse mais je ne sais pas comment récuperer des miniatures,j'ai mis un code qui recherche des *.jpg dans un dossier et qui me creer autant de panel dans un scrollbox que de fichiers trouvés, j'arrive a afficher les titres mais pas les images,
si quelqun peut m'aider,j'aimerais aussi récuperer le click des panels un peu comme le compo thumbs déja posté ici.
voici ce que j'utilise:

procedure TForm1.Button1Click(Sender: TObject);
var
i,x,y:integer;
frame:tpanel;
img:timage;
titre:tlabel;
trait:tbevel;
foundlist:tstringlist;
sr: TSearchRec;


begin
foundlist:=tstringlist.create;


if FindFirst(directorylistbox1.Directory+'\*.jpg', faAnyFile, sr) = 0 then
begin
foundlist.add(sr.name);
while FindNext(sr) = 0 do
foundlist.add(sr.name);
FindClose(sr);
end;
x:=0;
y:=0;
for i:=0 to foundlist.Count-1 do
begin
frame:=tpanel.Create(self);
frame.Parent:=scrollbox1;
frame.Caption:='';
frame.Height:=113;
frame.Width:=113;
frame.left:=x;
frame.top:=y;
titre:=tlabel.Create(self);
titre.Parent:=frame;
titre.Caption:=foundlist.Strings[i];
titre.Font.Size:=6;
titre.Height:=17;
titre.Width:=97;
titre.Top:=8;
titre.Left:=8;
trait:=tbevel.Create(self);
trait.Parent:=frame;
trait.Shape:=bsTopLine;
trait.Height:=1;
trait.Width:=97;
trait.Top:=32;
trait.Left:=8;
img:=timage.create(self);
img.Proportional:=true;
img.Stretch:=false;
img.center:=true;
img.Height:=65;
img.Width:=97;
img.Top:=40;
img.Left:=8;
inc(x,115);
if x>500 then
begin
x:=0; inc(y,115); end;
end;
end;

merci a tous ,
bye

12 réponses

Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
31 mars 2006 à 04:46
Salut,
Alors pour cela il te faut:
Créer une deuxième Form et tu y places un TImage dessus et tu mets la propriété AutoSize à True.
Créer un évènnement OnClick dans la Form principale
et l'affecter à chaque miniature.

TForm1 = class (TForm)
....
....
Procedure ImageClick(Sender : TObject);
private
{ Déclarations privées }
Public
{ Déclarations publiques }
End;

Implementation
Uses Unit2; // dans une deuxième (Form2) avec un TImage avec AutoSize à True
{$R *.dfm}

Procedure TForm1.ImageClick(Sender : TObject);
Begin
If (Sender is TImage) Then
Begin
Form2.Image1.Picture.Assign((Sender as TImage).Picture);
Form2.ShowModal;
End;
End;

Procedure TForm1.Button1Click(Sender: TObject);
...
Begin
...
Img: =Timage.Create(Self);
Img.Parent := Frame;
Img.Picture.LoadFromFile(FoundList.Strings[I]);
Img.OnClick := ImageClick;
Img.Proportional: =True;
Img.Stretch:=Talse;
Img.center:=True;
Img.Height:=65;
Img.Width:=97;
Img.Top:=40;
Img.Left:=8;
End;

La procédure OnClick (ImageClick) aurait pu être déclarée dans la deuxième form mais dans ce cas il faudrait adapter la procédure et son affectation (appel).

@+
Cirec
3
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
2 avril 2006 à 14:02
Pour vider la ScrollBox regarde le code juste au dessus il vide la ScrollBox juste avant de la remplir.

En suite pour charger l'aperçu avec un LoadFromFile il faut un peut modifier le code:

On se débrouille pour conserver l'indice de FoundList que l'on met dans le tag de Img
....
Tmp.LoadFromFile(FoundList.Strings[i]);
Img.Canvas.StrechDraw(Img.Canvas.ClientRect,Tmp)
Img.Tag := I;
....

Procedure TForm1.ImageClick(Sender : TObject);
Begin
If (Sender is TImage) Then
Begin
Form2.Image1.Picture.LoadFromFile(FoundList.Strings[(Sender as TImage).Tag]);
Form2.ShowModal;
End;
End;

J'ai pas testé mais ça devrait fonctionner

@+
Cirec
3
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
30 mars 2006 à 01:33
Salut,
essaye déjà en ajoutant ceci :

Img.Parent := Frame;
Img.Picture.LoadFromFile(FoundList.Strings[I]);

@+
Cirec
0
cs_saravana Messages postés 91 Date d'inscription vendredi 25 mars 2005 Statut Membre Dernière intervention 18 octobre 2007
30 mars 2006 à 20:11
merci s affiche les miniatures, il me reste un dernier probleme, c'est de récuperer le click pour qu'on puisse voir les images selectionnées en grande taille
merci,
bye
0

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

Posez votre question
cs_saravana Messages postés 91 Date d'inscription vendredi 25 mars 2005 Statut Membre Dernière intervention 18 octobre 2007
31 mars 2006 à 09:32
merci a toi cirec, tu m'a beaucoup avancé,
merci
bye
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
31 mars 2006 à 16:18
Par contre j'ai testé ton prog et il ne fait que créer des objets, mais jamais il ne les libères.
Donc si tu as des fichiers images, dans plusieurs répertoires et que tu les visites tous, la mémoire va saturer rapidement.
J'ai modifier un peut ton code afin qu'il libère les objets précédemment créer (si il y en a) pour ne pas avoir ce genre de souci.

Pour t'en rendre compte tu peux avant de faire les modifications démarrer le gestionnaire des tâches et repérer la mémoire utilisée
et charger (boutton1) plusieurs fois un répertoire (même si c'est le même) pour voir que l'occupation ne fait qu'accroître.

Et après modification tu refais le teste.


Procedure
TForm1.Button1Click(Sender:
TObject);
Var

I,
X,
Y
:
Integer;

Frame
:
TPanel;

Img
:
TImage;

Titre
:
TLabel;

Trait
:
TBevel;

Foundlist
:
TStringList;

Sr
:
TSearchRec;
Begin

FoundList
:=
TStringList.Create;

// Il faut absolument libérer les Objets que tu as crées avant sinon la mémoire
// risque de saturer très vite
With
ScrollBox1
Do

Begin

While
ControlCount
-
1
>
0
Do

Begin

If
(Controls[ControlCount
-
1]
Is
TPanel)
Then

(Controls[ControlCount
-
1]
As
TPanel).Free;

End;

End;

If
FindFirst(DirectoryListBox1.Directory
+
'\*.jpg',
faAnyFile,
Sr)
=
0
Then

Begin

FoundList.Add(Sr.Name);

While
FindNext(Sr)
=
0
Do

FoundList.Add(Sr.Name);

FindClose(Sr);

End ;

X
: =
0;

Y
:=
0;

For
I
: =
0
To
FoundList.Count
-
1
Do

Begin

Frame
:=
TPanel.Create(Self);

With
Frame
Do

Begin

Parent
: =
ScrollBox1;

Caption
:=
'';

Height
:=
113;

Width
:=
113;

Left
:=
x;

Top
:=
y;

End ;

Titre
: =
TLabel.Create(Self);

With
Titre
Do

Begin

Parent
:=
Frame;

Caption
:=
FoundList.Strings[i];

Font.Size
:=
6;

Height
:=
17;

Width
:=
97;

Top
:=
8;

Left
:=
8;

End ;

Trait
: =
TBevel.Create(Self);

With
Trait
Do

Begin

Parent
:=
Frame;

Shape
:=
bsTopLine;

Height
:=
1;

Width
:=
97;

Top
:=
32;

Left
:=
8;

End ;

Img
: =
TImage.Create(Self);

With
Img
Do

Begin

Parent
:=
Frame;

Picture.LoadFromFile(FoundList.Strings[I]);

OnClick
:=
ImageClick;

Proportional
:=
true;

Stretch
:=
False;

Center
:=
True;

Height
:=
65;

Width
:=
97;

Top
:=
40;

Left
:=
8;

End;

Inc(x,
115);

If
X
>
500
Then

Begin

X
: =
0;
Inc(y,
115);

End;

End;

FoundList.Free;
// et ne pas oublier de liberer dès qu'on en a plus besoin
End;

@+
Cirec
0
cs_saravana Messages postés 91 Date d'inscription vendredi 25 mars 2005 Statut Membre Dernière intervention 18 octobre 2007
2 avril 2006 à 09:20
merci cirec mais lorsque je sroll ma scrollbox il met un tps fou pour actualiser surtout si on a plus de 100 photos haute résolution,du coup j'ai essayé en crééant
var
tmp:tjpegimage;
begin
...
tmp:=tjpegimage.create;
tmp.performance:=jpbestspeed;
tmp.scale:=jseighth;
tmp.loadfromfile(foundlist.strings[i]);
img.canvas.strrechdraw(img.canvas.clientrect,tmp)

dans ce cas l'actualisation est rapide et le chargement aussi mais lorsque jouvre en grande taille c limage qui est dans img qui est agrandi , du coup ila beaucoup de carreaux,il y aura pas un moyen de loadfromfile?
sinon j'ai une derniere question, comment on fait pour vider le ontenu d'un scrollbox
merci
bye
0
cs_saravana Messages postés 91 Date d'inscription vendredi 25 mars 2005 Statut Membre Dernière intervention 18 octobre 2007
2 avril 2006 à 15:00
merci a toi cirec ton code est 100% operationnel et la différence de tps de chargement saute aux yeux.
bye
0
cs_saravana Messages postés 91 Date d'inscription vendredi 25 mars 2005 Statut Membre Dernière intervention 18 octobre 2007
2 avril 2006 à 20:14
j'ai encore besoin de ton aide ,tout marche dans mon appli a part que je n'arrive pas a faire suivant et précédant pour voir les autres images sans passer par les minatures,
merci
bye
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
3 avril 2006 à 01:45
tu veux dire pendant que tu visualises tu voudrais pouvoir passer directement à la suivante où la précédente

@+
Cirec
0
cs_saravana Messages postés 91 Date d'inscription vendredi 25 mars 2005 Statut Membre Dernière intervention 18 octobre 2007
3 avril 2006 à 11:50
exactement!
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
3 avril 2006 à 15:52
Bon alors quelques petits changements s'imposent :


En premier dans la Form principale (Form1) :

.....
Public
{ Déclarations publiques }
End;
Var
Form1 : TForm1;
Foundlist : TStringList;
Implementation
Uses Unit2;
{$R *.DFM}
Procedure TForm1.Button1Click(Sender: TObject);
Var
I, X, Y : Integer;
Frame : TPanel;
Img : TImage;
Titre : TLabel;
Trait : TBevel;
Sr : TSearchRec;
Begin
// Il faut absolument libérer les Objets que tu as crées avant sinon la mémoire
// risque de saturer très vite
With ScrollBox1 Do // Il faut absolument mettre ceci pour libérer la mémoire
Begin
While ControlCount - 1 > 0 Do
Begin
If (Controls[ControlCount - 1] Is TPanel) Then
(Controls[ControlCount - 1] As TPanel).Free;
End;
End; // Jusque ici

If FindFirst(DirectoryListBox1.Directory + '\*.jpg', faAnyFile, Sr) = 0 Then
Begin
FoundList.Add(Sr.Name);
While FindNext(Sr) = 0 Do
FoundList.Add(Sr.Name);
FindClose(Sr);
End;
X := 0;
.......
End ;


Procedure
TForm1.ImageClick(Sender: TObject);
Begin

If (Sender Is TImage) Then
Begin

Form2.Image1.Picture.LoadFromFile(FoundList.Strings[(Sender as TImage).Tag]);
Form2.Image1.Tag : = (Sender as
TImage).Tag; // pour pouvoir récuperer le n° de
// l'image dans la deuxième Form
Form2.ShowModal;
End
;
End
;
// il faut déclarer la liste comme ceci
procedure TForm1.FormCreate(Sender:
TObject);
begin

FoundList := TStringList.Create;
end
;
// et la libérer comme ceci
procedure TForm1.FormClose(Sender: TObject; var
Action: TCloseAction);
begin

FoundList.Free; // et ne pas oublier de liberer dès qu'on en a plus besoin
end;
End.

En second dans la Form2 (Visualisation) :

Tu mets la propriété KeyPreview à True avec l'inspecteur d'objet et :


type


TForm2 = class(TForm)
Image1: TImage;
procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
private
{ Déclarations privées }
public
{ Déclarations publiques }

end;

var
Form2: TForm2;

implementation
{$R *.DFM}
Uses Unit1;
// Indispensable pour avoir accès à la la list (FoundList)


// VK_BROWSER_BACK = 166; j'ai mis les valeurs des deux touches ici au cas ou ...
// VK_BROWSER_FORWARD = 167;
procedure TForm2.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
Var Index : Integer;

begin
If FoundList.Count < 1 Then Exit;
Index : = Image1.Tag; // on récupère l'index en cours
If Key = VK_BROWSER_BACK Then // Précédant

Begin
If Index > 0 Then Dec(Index) Else Index : = FoundList.Count -1 ; // on vérifie les limites avant de retirer 1
Form2.Image1.Picture.LoadFromFile(FoundList.Strings[Index]); // et on affiche l'image
End;
If Key = VK_BROWSER_FORWARD Then // Suivant

Begin
If Index < FoundList.Count -1 Then Inc(Index) Else Index : = 0 ; // on vérifie les limites avant d'ajouter 1
Form2.Image1.Picture.LoadFromFile(FoundList.Strings[Index]); // et on affiche l'image
End;
Image1.Tag := Index; // et pour finir on mémorise l'index de l'image dans le Tag pour pouvoir répéter l'opération
end;
end.

Voilà je pense que c'est tout
Bonne prog et

@+
Cirec
0
Rejoignez-nous