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

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Delphi : utilisation ludique d'un style FMX (jeu de taquin)
Un billet blog de Serge Girard

Le , par SergioMaster

0PARTAGES

L'objectif de ce billet n'est pas de refaire une nouvelle version d'un jeu de Taquin que vous pourrez retrouver dans cette discussion.

Lors de l'écriture de la version FMX de ce jeu, une idée, en relation avec mes travaux sur les styles, m'a titillé : était-il possible d'utiliser un style pour charger les pièces du puzzle ? L'utilisation de la palette Style m'était jusqu'à présent plutôt "terra incognita" et ses objets souvent source de frustrations au cours de mes divers démêlés avec les styles.


Je tiens à souligner qu'il s'agit bien des styles FMX, ceux utilisés en VCL sont beaucoup plus "figés" et, s'il y a similitudes et possibilités de transformation de l'un vers l'autre mes "recherches" n'ont pas été plus loin dans cette direction.

L'occasion faisant donc le larron, je me suis donc mis en tête de créer un style qui contiendrait l'image de mon puzzle ainsi que la découpe de ses différentes pièces.
Un outil est proposé : le concepteur de style de bitmaps et c'est d'abord par là que mes efforts se sont portés. Mal m'en a pris pour une première utilisation, ce fut un échec total ! J'en ai certainement mal compris les arcanes ou l'outil n'est pas fait pour l'objectif fixé.
Je suis alors passé par ce que je connais mieux : le dépôt d'un TStyleBook sur une forme et l'ouverture de son éditeur.

Voilà ce que je veux obtenir :


Je vais maintenant indiquer les diverses étapes qui m'ont été nécessaires pour réaliser cela.
Mais, tout d'abord, notez que le style sera un style dit 'Default' afin qu'il s'applique quelle que soit la plateforme cible.

  • Double-cliquez sur le composant StyleBook1 déposé sur la forme afin d'ouvrir le concepteur de styles.
  • Glissez-déposez ensuite un TImage dans l'arborescence du StyleContainer.



  • Chargez une image (propriété MultiResBitmap) et changer la propriété StyleName en quelque chose de plus "parlant" que le nom par défaut proposé Image1Style(un nom neutre me sera utile plus tard aussi utiliserai-je 'modele' pour la suite).



Il est désormais temps de créer notre première pièce du puzzle.
  • Glissez-déposez un TLayout au niveau de la racine (StyleContainer) et dans ce TLayout, auquel vous aurez changé la propriété StyleName en 'piece01', ajoutez un TStyleObject.
  • Changez la propriété StyleLookup du StyleObject créé (y mettre le StyleName du TImage).
  • Utilisez le bouton proposé par la propriété SourceLink qui va ouvrir une nouvelle fenêtre, Éditeur BitmapLinks.




  • La première chose à faire est de réduire le zoom de façon à visualiser l'image entière.
  • Agrippez les deux coins jaunes de façon à retailler la zone à définir. Quand vous les déplacerez, les valeurs TBounds (en haut de la fenêtre) se modifieront. L'objectif est d'obtenir une taille de 100 x 100 (mon image de base étant en 400 x 400).

Ce n'est pas forcément évident au début, ne vous focalisez pas trop sur des délimitations juste, nous verrons plus tard comment ranger cela.
  • Refaites alors les opérations pour chaque pièce.

Le refaire pour chaque pièce, même s'il y en a que 16, c'est long ! Toutefois, pour comprendre certains principes et avant que j'explique comment
créer ces pièces plus rapidement, prenez le temps de créer la pièce numéro 2 (à droite de la première, TBounds(100,00,0,00)-(200,00,100,00)) et celle qui sera sous la première (pièce numéro 5, TBounds(0,00,100,00)-(100,00,200,00)).

Je vous livre donc l'astuce, pour éviter ces répétitions et corriger les petits défauts de positions :
  • Sauvegardez votre style (vous avez un bouton pour cela). Assurez vous de bien utiliser l'extension .style pour obtenir une version texte de ce dernier, l'extension .fsf produira une version "compilée", j'écrirai plutôt compressée, illisible.
  • Ouvrez le fichier créé avec un outil tel que Notepad++.


Code XML : Sélectionner tout
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
  
object TStyleContainer 
  object TImage 
    StyleName = 'modele' 
    MultiResBitmap.Height = 400 
    MultiResBitmap.Width = 400 
    MultiResBitmap = < 
      item 
        Width = 400 
        Height = 400 
        PNG = { 
          89504E470D0A1A0A0000000D494844520000019000000190080600000080BF36 
          CC000000017352474200AECE1CE90000000467414D410000B18F0BFC61050000 
          FFBA49444154785EECBD07A0654771E75D2FE737392AA2882414404248800011 
<!-- je vous fais grâce des quelque 2700 lignes suivantes de l''image --> 
         66FB0FEEB55FF8D0476CDFCEFD9136373F671DED1DE107350352A142850A152A 
          340EB3FF13E4E33CC0A3EE7CFE0000000049454E44AE426082} 
        FileName =  
          'D:\serge\Documents\Embarcadero\Studio\Projets\Sidney\stoneedge.png' 
      end> 
    Align = Center 
    Size.Width = 274.000000000000000000 
    Size.Height = 269.000000000000000000 
    Size.PlatformDefault = False 
    Visible = False 
  end 
  object TLayout 
    StyleName = 'piece01' 
    Align = Center 
    Visible = False 
    TabOrder = 3 
    object TStyleObject 
      StyleName = 'StyleObject1Style' 
      SourceLookup = 'Modele' 
      SourceLink = < 
        item 
          SourceRect.Left = 2.000000000000000000 
          SourceRect.Top = 1.000000000000000000 
          SourceRect.Right = 100.000000000000000000 
          SourceRect.Bottom = 100.000000000000000000 
        end> 
    end 
  end 
  object TLayout 
    StyleName = 'piece02' 
    Align = Center 
    Visible = False 
    TabOrder = 2 
    object TStyleObject 
      StyleName = 'StyleObject1Style' 
      SourceLookup = 'Modele' 
      SourceLink = < 
        item 
          SourceRect.Left = 100.000000000000000000 
          SourceRect.Right = 200.000000000000000000 
          SourceRect.Bottom = 100.000000000000000000 
        end> 
    end 
  end 
  object TLayout 
    StyleName = 'piece05' 
    Align = Center 
    TabOrder = 1 
    object TStyleObject 
      StyleName = 'StyleObject1Style' 
      SourceLookup = 'Modele' 
      SourceLink = < 
        item 
          SourceRect.Top = 100.000000000000000000 
          SourceRect.Right = 100.000000000000000000 
          SourceRect.Bottom = 200.000000000000000000 
        end> 
    end 
  end 
 end

Ce qui nous intéresse, c'est un bloc de TLayout, définissant une piéce
Code XML : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  
  object TLayout 
    StyleName = 'piece01' 
    Align = Center 
    Visible = False 
    TabOrder = 3 
    object TStyleObject 
      StyleName = 'StyleObject1Style' 
      SourceLookup = 'Modele' 
      SourceLink = < 
        item 
          SourceRect.Left = 2.000000000000000000 
          SourceRect.Top = 1.000000000000000000 
          SourceRect.Right = 100.000000000000000000 
          SourceRect.Bottom = 100.000000000000000000 
        end> 
    end 
  end
Il suffira de le reproduire par copier-coller en changeant la propriété StyleName et les différentes propriétés de SourceLink pour obtenir un découpage parfait. Une fois fait :
  • Sauvegardez le fichier modifié.
  • Revenez à l'IDE Delphi et à votre programme.
  • Chargez à nouveau le style (pour récupérer les modifications faites).


Il ne reste plus qu'à utiliser le style.
N'oubliez pas, même si la clôture de l'onglet Concepteur de styles se charge de vous le rappeler, d'appliquer le style (bouton le plus à droite).

Dans la deuxième image de cet article, pour illustrer l'objectif, j'ai utilisé un TGridLayout pour contenir des TPanels qui, eux, auront chacun une propriété StyleLookup différent.
Il n'est pas sûr que le TGridLayout soit le composant le plus adapté pour codifier le jeu, mais, il n'était pas non plus dans mes desseins que de le faire.

Par contre, je me suis plus attardé sur l'image, était-il possible de changer l'image utilisée dans le style à l'exécution ?
J'aurais, bien sûr, pu faire un style par image, mais ma curiosité m'a poussé à le vérifier.
De l'idée, loufoque, à la réalisation, il ne m'a fallu qu'un peu de code et quelques explorations de solutions concernant l'application du style ainsi modifié.

Code Delphi : Sélectionner tout
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
  
procedure TMainForm.ButtonChangeImageClick(Sender: TObject); 
var pStream : TMemoryStream; 
    pFMXObj : TFMXObject; 
begin 
  
// Passage de l'image via un stream 
pStream:=TMemoryStream.Create; 
try 
  PStream.LoadFromFile('test1.png'); 
  pFMXObj:=StyleBook1.Style.FindStyleResource('modele'); 
  if Assigned(pFMXObj) then 
    begin 
      PStream.Position:=0; 
      TImage(pfMXObj).Bitmap.LoadFromStream(Pstream); 
    end; 
finally 
  pStream.Free; 
end; 
  
//pFMXObj:=StyleBook1.Style.FindStyleResource('modele'); 
//if Assigned(pFMXObj) then 
//    begin 
//      TImage(pfMXObj).Bitmap.LoadFromFile('test1.png'); 
//    end; 
  
// Forcer le dessin du GridLayout 
GridLayout1.BeginUpdate; 
GridLayout1.EndUpdate; 
  
// variante Repaint par piece 
//for var i:= 0 to GridLayout1.ChildrenCount-1 do 
//  TPanel(Gridlayout1.Children[i]).Repaint; 
  
  
// Variante re-dessin complet 
//for var i:= GridLayout1.ChildrenCount-1 downto 0 do 
//  Gridlayout1.Children[i].Free; 
// 
//for var i := 1 to 16 do 
//   begin 
//     with TPanel.Create(Self) do 
//      begin 
//         StyleLookup:=Format('piece%.2d',[i]); 
//         Parent:=GridLayout1; 
//     end; 
//   end; 
end;



Je suis prêt à parier qu'il y a encore d'autres solutions code que je n'ai pas explorées à l'heure actuelle.
Je gage aussi que changer le découpage de pièces en fonction de la taille de l'image (j'ai triché en utilisant des images de tailles identiques de 400x400) l'est tout autant. C'est une autre histoire à écrire. Atteindre les propriétés de SourceRect ne sera pas aussi simple.

En tout cas, j'espère que cette utilisation "ludique" des styles FMX changera peut-être votre opinion sur ceux-ci.

Une erreur dans cette actualité ? Signalez-le nous !