Comment créer une liste d'images
Bonjour.
Pour profiter de ma période de confinement, j'ai entrepris de transcrire une Réussite «FreeCell» que j'avais écrite en Delphi7 (qui fonctionne très bien), en Lazarus.
Pour cela j'utilise des listes d'images, des listes de « Records » et des listes de listes. Avec toutes ces listes, le compilateur ne trouve pas d'erreurs sauf quelques conseils, mais le programme se termine par une « Classe d'exception:External SIGSEGV »
Pour déboguer la création de la liste d'images j'ai écrit un petit programme test dont voici l'unité principale :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| unit ListeTest_P;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Image1: TImage;
Image10: TImage;
Image11: TImage;
Image12: TImage;
Image13: TImage;
Image14: TImage;
Image15: TImage;
Image16: TImage;
Image0: TImage;
Image2: TImage;
Image3: TImage;
Image4: TImage;
Image5: TImage;
Image6: TImage;
Image7: TImage;
Image8: TImage;
Image9: TImage;
Panel1: TPanel;
Panel2: TPanel;
procedure FormCreate(Sender: TObject);
procedure CreerListIm(Sender:TObject);
private
public
end;
var
Form1: TForm1;
Image0,Image1,Image2,Image3,Image4,Image5,Image6,Image7,Image8,Image9,
Image10,Image11,Image12,Image13,Image14,Image15,Image16:TImage;
ListIm:TList;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
ListIm.Create;
CreerListIm(Sender);
end;
procedure TForm1.CreerListIm(Sender:TObject);
var
n:integer;
s:string;
begin
ListIm.Add(Image0);//Sert à afficher la pioche (centre haut, index 0)
ListIm.Add(Image1);//Première colonne bas(index 1)
ListIm.Add(Image3);
ListIm.Add(Image4);
ListIm.Add(Image5);
ListIm.Add(Image6);
ListIm.Add(Image7);
ListIm.Add(Image8);//Dernière colonne bas(index 8)
ListIm.Add(Image9);//Première colonne haut(index 9)
ListIm.Add(Image10);
ListIm.Add(Image11);
ListIm.Add(Image12);//Dernière colonne haut(index 12)
ListIm.Add(Image13);//Première colonne de dépôt
ListIm.Add(Image14);
ListIm.Add(Image15);
ListIm.Add(Image16);//Dernière colonne de dépôt
n:=ListIm.Count;
str(n,s);
Panel2.Caption:=s;
end;
end. |
La fonction ListIm.Add() nécessite pour attribut un pointeur, est-ce que l'erreur viendrait de là ? Dans ce cas, comment créer un pointeur sur chaque image ?
Ensuite comment accéder à une image de la liste pour par exemple modifier sa taille ?
Un grand merci à ceux qui voudront bien se pencher sur mon problème.
Comment créer une liste d'images sou Lazarus
Bonjour
Merci pour ta réponse mais je n'ai pas été assez clair dans ma question.
La réussite FreeCell est constitué de 16 emplacements sur lesquels sont déposés des cartes. Il y a 8 emplacements dont la taille est fixe (une seule carte visible) et 8 dont la hauteur est variable. Ce sont ces emplacements sur le tapis qui sont des images. Les cartes déposés sur lmage1 forment une liste de cartes et les 16 listes de cartes forment une liste de listes.
Sous Delphi7 toutes ces listes sont facilement constituées avec :
ListIm.Add(Image1) où Image1 est un TImage
List1.Add(P) où P est un pointeur sur une carte
Liste.Add(List1) où List1 est la liste des cartes déposées sur l'Image1.
La taille de l'Image doit être ajustée en fonction du nombre de cartes déposées.
List1.Count est le nombre de cartes déposées sur Image1.
Liste est la liste des 16 listes contenant les cartes.
Je cherche donc l'équivalent avec Lazarus
TimageList et TobjectList ne conviennent pas pour ce que je cherche.
A+
JC
Comment créer une liste d'images
Citation:
Envoyé par
ChPr
Il y a aussi un autre problème : vous définissez deux fois les variables 'Image_xx' ?
Cordialement.
Pierre.
Bonjour
Si je ne déclare pas les Imagexx comme variables le compilateur affiche "Succès" mais le programme s'arrête quand même avec l'erreur "SIGSEGV".
La déclaration des Imagexx comme variables n'est donc pas nécessaire.
Cordialement
JC
Comment créer une liste d'images
Bonjour Pierre
Effectivement je viens de tester
Code:
ListIm:=TListCreate
et ça fonctionne ! Merci
C'était une erreur impardonnable de ma part.
Pour ce qui concerne la modification de la taille de l'image, c'était un exemple. J'aurais aussi bien pu demander comment changer le curseur sur cette image.
Lorsque je veux intervenir sur une image de ma liste, il faut que je l'extraie de la liste, je modifie la propriété de l'image, puis je la réintègre dans la liste.
Sous Delphi je procède de la manière suivante:
Code:
1 2 3 4 5 6
| var
Imagea:TImage;
i:integer;
Imagea:=ListIm[i];//pour modifier l'image d'index i
Imagea.Height:=120;
ListIm[i]:=Imagea |
Or Lazarus n'accepte pas
il veut un pointeur! Quel est ce pointeur?
Cordialement
JC
Comment créer une liste d'images
Citation:
Envoyé par
BeanzMaster
Bonjour
Essayes en ajoute @ devant tes objets List1.Add(@P)Pour ce qui est du change de taille de tes TImage tu as les propriétés "Stretch" et "Proportionnal" qui feront que l'image s'adaptera aux dimension de ton contrôle
A+
Jérôme
Bonjour Jérôme
Merci pour ta réponse.
Je ne pense pas que les propriétés "Stretch" et "Proportionnal" soient adaptées à mon cas, il me semble qu'ils adaptent la taille du bitmap (en le déformant) à la taille du conteneur Image.
Je cherche une méthode plus générale pour modifier une propriété d'une image de la liste, par exemple modifier le curseur.
Pour modifier la hauteur de l'image d'index 2 j'ai écrit la procédure suivante qui passe sans message du compilateur mais qui se termine par une erreur "SIGSEGV".
Code:
1 2 3 4 5 6 7 8 9 10
|
procedure TForm1.ModifImage(Sender:TObject);
var
P:^TImage;
begin
P:=ListIm[2];
Image0:=P^; //Image0 n'est pas utile dans mon programme
Image0.Height:=120;
ListIm[2]:=P;
end; |
Je pense que l'erreur provient de la définition du pointeur.
Comment modifier cette procédure pour que ça fonctionne?
Cordialement
JC
Comment créer une liste d'images
Citation:
Envoyé par
ChPr
Quand vous avez enregistré vos images dans la liste, Pour chacune, vous n'avez fait qu'y enregistrer un pointeur sur cette image. Donc, quand vous faites Imagea:=ListIm[i];, vous ne faites que récupérer son pointeur. Mais comme un pointeur ne dit rien de la structure de l'objet qui a été enregistré, vous ne pouvez rien en récupérer. Pour cela, il faut que vous fassiez un transtypage, c'est-à-dire : Imagea:=TImage(ListIm[i]);.
Mais avant tout, vous avez enregistré des images inexistantes puisque vous ne les avez pas créées. Le fait de les avoir déclarées en tant que TImage n'a fait qu'installer une variable pointant sur 'nil'.
Donc, avant toutes choses, vous devez créer ces images par Image_xx:= TImage.Create(Self); ; vous pourrez avoir accès ensuite à leurs propriétés.
Par ailleurs, une fois que vous avez changé les paramètres d'une image, ce n'est pas la peine de réenregistrer son pointeur (ListIm[i]:=Imagea;) ; il n'a pas changé.
Cordialement.
Pierre.
Bonjour Pierre
Je vous ai répondu hier pour vous dire que vos conseils fonctionnent parfaitement en créant les images avec Image_xx:=TImage.Create(Self) ;Le message n'a pas du passer parce que trop long, j'avais ajouté le code de l'unité principale.
Pour compléter mon programme ListeTest, j'ai voulu vérifier que l'affichage des cartes se faisait bien sur les images.
Après avoir :
ajouté dans uses : LResources et LCLType
dans public :
procedure LoadBitmapFromResource(Const ResName : String; Bmp : Tbitmap);la directive {$R Cartes.res} contenant les cartes
J'ai ajouté la procédure suivante simplement destinée à afficher l'as de cœur sur l'Image1 :
Code:
1 2 3 4 5 6 7 8 9 10 11
|
procedure TForm1.Afficher(Sender:TObject);
var
Imagea:TImage;
Bmp:TBitmap;
begin
Bmp:=TBitmap.Create;
Imagea:=TImage(ListIm[1]);
Bmp.LoadFromResourceName(HInstance,'C011');
Imagea.Canvas.Draw(0,0,Bmp);
end; |
Le compilateur affiche bien le message « Succès » mais l'as de cœur ne s'affiche pas ! Où est l'erreur ?
Comment créer une liste d'images
Citation:
Envoyé par
ChPr
Qu'y a-t-il exactement maintenant dans cette procédure que vous avez dû modifier.
Cordialement.
Pierre
Bonjour Pierre,
La procédure que j'ai supprimée du programme est justement celle qui crée la liste des images,
Code:
1 2 3 4 5 6 7 8 9 10 11 12
|
procedure TForm1.CreerListIm(Sender:TObject);
begin
Image0:=TImage.Create(Self);
Image1:=TImage.Create(Self);
//.......
Image16:=TImage.Create(Self);
ListIm.Add(Image0);//Sert à afficher la pioche (centre haut, index 0)
ListIm.Add(Image1);//Première colonne bas(index 1)
//.....
ListIm.Add(Image16);//Dernière colonne de dépôt
end; |
Cordialement
JC
Comment créer une liste d'images
Citation:
Envoyé par
BeanzMaster
Bonsoir,
J'ai du mal à comprendre ta logique avec tous ces TImages et cette liste basée dessus. Pourrais tu nous faire un petit zip des sources de ton projet avec le fichier "card.res" pour que l'on puisse y jeter un oeil, tester et t'aider du mieux possible.
J'ai l'impression que ton approche n'est pas la plus facile à mettre en place, j'ai l'impression que tu te complique la vie.
Une petit plus serait également de nous décrire les règles de jeux de ton solitaire.
A+
Jérôme
Bonjour Jérôme,
Le but de ce programme n'est pas de créer un FreeCell puisque je l'ai déjà écrit en Delphi7 et il fonctionne très bien. Le but est plutôt de me familiariser avec Lazarus. En essayant de le transcrire dans ce langage je suis tombé sur le problème de la création des listes et comme je n'aime pas abandonner j'ai créé ce groupe de discussion.
Voici en simplifié, les règles du jeu du FreeCell:
Le tapis est composé de trois parties:
La partie inférieure est composée de 8 cases (ce sont les images de 1 à 8).
Au démarrage du jeu les 52 cartes sont distribuées sur ces 8 images, il y a donc 4 images avec 7 cartes et 4 images avec 6 cartes. Les cartes sont décalées pour qu'elles soient toutes visibles.
La partie supérieure est divisée en deux parties:
A gauche 4 Images ne pouvant accueillir qu'une seule image à la fois, elles servent à dégager les cartes gênantes.
A droite 4 Images destinées à recevoir les cartes de la même couleur dans l'ordre. Par exemple: sur la première case les cœurs en commençant par l'as puis 2 jusqu'au roi. Seule la dernière carte déposée est visible (pas de décalage). Le jeu est terminé et réussi lorsque toutes les 4 cases affichent un roi, toutes les autres cases sont alors vides.
N'importe quelle carte peut être déposée sur les 4 cases en haut à gauche.
Pour déplacer une carte d'une des 8 images du bas il faut que celle-ci soit de valeur directement inférieure et de couleur différente à celle sur laquelle on la dépose.
(ex:un 7 de cœur peu être déposé sur un 8 de pique...)
Il est même possible de déplacer un groupe de cartes si celui-ci est ordonné (ordre croissant et couleurs alternées, s'il y a des cases de libre en haut à gauche ou en bas).
Pour réussir il faut donc:
essayer de libérer les as pour commencer, sans encombrer toutes les cases en haut à gauche.
De jongler en déplaçant les cartes du bas pour caser les 2, 3...jusqu'au roi.
Pour ce qui concerne mon programme :
chaque carte est un Record qui contient le nom du fichier inclus dans Cartes.res (ex:C011.bmp pour le roi de cœur) et un booléen pour l'affichage en vidéoinverse.
Les cartes affichées dans l'Image1 (première image du bas) forment Liste1, les cartes déposées sur l'Image16 (dernière image en haut à droite) forment Liste16.
Liste0 sera formée par les cartes en cours de déplacement.
Liste est composée des 17 listes d'index 0 à 16.
ListIm est une liste contenant les 17 images (Image0 n'est pas utiliée)
Pour déplacer une carte, je clique sur la carte à déplacer et j'en déduis par son index l'Image_s source et la Liste_s source puis je clique sur l'Image de destination, j'ai alors l'Image_d et Liste_d, il me reste alors à comparer la carte source à la dernière carte de la liste de destination.
L'intérêt des listes est multiple dans ce programme:
- je place à l'index 0 des listes de cartes une carte factice indiquant les emplacements où cliquer
-j'affiche ensuite automatiquement ces cartes en utilisant la liste des images...etc le tout sans clic.
J'espère que ma démarche pour la conception de ce programme est un peu plus claire!
Quant au zip de mon source, je veux bien l'envoyer mais je ne sais comment, je ne maîtrise pas assez ce moyen de correspondance.
A+
JC
1 pièce(s) jointe(s)
Comment créer une liste d'images
Citation:
Envoyé par
BeanzMaster
Petite erreur dans le code
il faut changer la méthode
function TMainForm.ValidationCarteSurTasDeCarte(IndexListe : Integer; CarteADeposer : PCarte) : Boolean;par
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
function TMainForm.ValidationCarteSurTasDeCarte(IndexListe : Integer; CarteADeposer : PCarte) : Boolean;
Var
Carte : PCarte;
Liste : TList;
begin
Result := False;
Liste := RetourneListeSuivantIndex(IndexListe);
if Liste.Count < 1 then Exit(true); //------> Ligne à ajouter
Carte := Liste.Items[(Liste.Count - 1)]; // On recupere la derniere carte
Case Carte^.Couleur of
ccCoeur, ccCarreau : Result := (CarteADeposer^.Couleur = ccPique) or (CarteADeposer^.Couleur = ccTrefle);
ccPique, ccTrefle : Result := (CarteADeposer^.Couleur = ccCoeur) or (CarteADeposer^.Couleur = ccCarreau);
end;
if Result then
begin
Result := Result and (Carte^.Valeur > CarteADeposer^.Valeur);
end;
end; |
Bonjour Jérôme,
Après une pause pour fêter le déconfinement, les affaires reprennent.
Je n'ai pas encore étudié votre programme, je m'y attelle aujourd'hui, mais je ne résiste pas à l'envie de vous envoyer le source du FreeCell en Delphi.
Je demande simplement de l'indulgence pour ma manière de programmer mais toutes les critiques seront les bienvenues.
A+
JC
comment créer une liste d'images
Salut,
Le but de la transcription de mes programmes de Delphi en Lazarus est justement le Drag and Drop...
Amicalement
JC
Comment créer une liste d'images
Bonjour,
Je reste sur ma faim pour ce qui concerne la gestion des listes d'images et listes de listes. J'ai néanmoins appris à m'en passer en utilisant des tableaux à la place.
Je remercie tous ceux qui ont bien voulu participer à cette discussion, en particulier Jérôme, Pierre, Jipété, Nullosse... et qui y ont consacré du temps.
Si d'ici demain soir personne n'y a rajouté de commentaire je déclarerai la discussion close.
Cordialement
JC