Bonjour,
toujours à fond dans mon délire j'entame une nouvelle étape : la création d'un équivalent TDBRadioGroupBox.
Mes premiers essais en créant le composant au runtime sont plus ou moins concluant
Premiers essais en utilisant une propriété TStrings
utilisation
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
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176 TRadioGroupBoxPair = Class(TGroupBox) private FColumns : Word; FValue : String; FItems : TStrings; FIndexItem : Integer; CBLayout : TGridLayout; procedure SetColumns(const Value: word); procedure SetValue(const Value: string); procedure Change(Sender : TObject); procedure SetIndexItem(const Value: Integer); procedure SetItems(const Value: TStrings); protected function FindValue(const V : String) : Integer; procedure OnResize; public constructor Create(AOwner : TComponent); override; destructor Destroy; override; procedure AddItem(const Text : String; const Value : String); function Paint : Boolean; reintroduce; published property Items : TStrings read FItems write SetItems; property Value : String read FValue write setValue; property IndexItem : Integer read FIndexItem write SetIndexItem; property Columns : word read FColumns write SetColumns stored Paint; end; implementation { TRadioGroupBoxPair } procedure TRadioGroupBoxPair.AddItem(const Text, Value: String); var ARadio : TRadioButton; begin FItems.AddPair(Text,Value); if FItems.Count>0 then CBLayout.ItemHeight:=CBLayout.Height/(FItems.Count*FColumns) else CBLayout.ItemHeight:=CBLayout.Height; ARadio:=TRadioButton.Create(CBLayout); ARadio.Parent:=CBLayout; ARadio.Text:=Text; ARadio.Tag:=FItems.Count+1; ARadio.TagString:=Value; ARadio.OnChange:=Change; ARadio.Name:=format('%sRadio%d',[self.Name,FItems.Count]); end; procedure TRadioGroupBoxPair.Change(Sender: TObject); var i : Integer; AObject : TFMXObject; begin for i:=0 to Pred(CBLayout.Children.Count) do begin AObject:=CBLayout.Children[i]; if AObject is TRadioButton AND TRadioButton(AObject).IsChecked then begin FValue:=AObject.TagString; FIndexItem:=AObject.Tag; Break; end; end; end; constructor TRadioGroupBoxPair.Create(AOwner: TComponent); begin inherited; FIndexItem:=-1; FColumns:=1; Width:=200; Padding.Top:=20; Padding.Left:=3; Padding.Bottom:=3; Padding.Right:=3; CBLayout:=TGridLayout.Create(Self); CBLayout.Name:=Self.Name+'CBLayout'; CBLayout.ItemHeight:=Width-Padding.Left-Padding.Right; CBLayout.ItemHeight:=24; CBLayout.Parent:=Self; CBLayout.Align:=TAlignLayout.Client; CBLayout.OnDragOver:=OnDragOver; FItems:=TStringList.Create; end; destructor TRadioGroupBoxPair.Destroy; begin FreeAndNil(CBLayout); FreeAndNil(FItems); inherited; end; function TRadioGroupBoxPair.FindValue(const V: String): Integer; var i : Integer; begin result:=-1; for i:=0 to Pred(FItems.Count) do if //FItems.Values[FItems.Names[i]]=V FItems.ValueFromIndex[i]=V then begin result:=i; exit; end; end; procedure TRadioGroupBoxPair.OnResize; begin Paint; end; function TRadioGroupBoxPair.Paint : Boolean; var Rows : word; begin CBLayout.Width:=Self.Width-Padding.Top-Padding.Bottom; CBLayout.ItemWidth:=CBLayout.Width/FColumns; CBLayout.Height:=Self.Height-Padding.Top-Padding.Bottom; if FItems.Count>0 then begin Rows:=FItems.Count mod FColumns; Rows:=IfThen(Rows>0,FItems.Count div FColumns +1,FItems.Count div FColumns); CBLayout.ItemHeight:=CBLayout.Height/Rows; end; result:=true; end; procedure TRadioGroupBoxPair.SetColumns(const Value: word); begin if FColumns<>Value then begin FColumns := Value; Paint; end; end; procedure TRadioGroupBoxPair.SetIndexItem(const Value: Integer); var aRB : TFMXObject; begin if Value <> FIndexItem then begin FIndexItem := Value; if FIndexItem>=0 then TRadioButton(CBLayout.Children[FIndexItem]).IsChecked:=true else for aRB in CBLayout.Children do if aRB is TRadioButton then TRadioButton(aRB).isChecked:=False; Paint; end; end; procedure TRadioGroupBoxPair.SetItems(const Value: TStrings); var i : Word; begin if FItems.CommaText<>Value.CommaText then begin CBLayout.DeleteChildren; for i:=0 to Pred(Value.Count) do AddItem(Value.Names[i],Value.Values[Value.Names[i]]); Paint; end; end; procedure TRadioGroupBoxPair.setValue(const Value: String); begin FValue := Value; FIndexItem:=FindValue(Value); if FIndexItem>=0 then begin TRadioButton(CBLayout.Children[FIndexItem]).IsChecked:=true; Paint; end; end;
Au niveau du runtime cela fonctionne. Inconvénient quand il s'agit d'en faire un composant donc au moment du design, remplir la liste des boutons via un TStrings c'est pas très naturel
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 RB:=TRadioGroupBoxPair.Create(Self); Rb.Text:='Essai'; Rb.Columns:=Word(Trunc(SpinBox1.Value)); RB.Parent:=Self; RB.Position.X:=230; RB.Position.Y:=15; RB.AddItem('Valeur 1','1'); RB.AddItem('Valeur 2','2'); RB.AddItem('Valeur 3','3'); RB.Paint;
j'ai donc changé ma propriété en TCollectionValeur 1=1
Valeur 2=2
Valeur 3=3
Ce qui me permet de proposer ce genre de saisie des différents Items
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
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 TItem = Class (TCollectionItem) private FTexte : String; FValeur : STring; procedure SetTexte(const Value: String); procedure SetValeur(const Value: String); published property Texte : String read FTexte write SetTexte; property Valeur : String read FValeur write SetValeur; end; TItemCollection<T: TItem> = class(TCollection) protected function GetItem(Index: Integer): T; procedure SetItem(Index: Integer; Value: T); procedure Notify(Item: TCollectionItem; Action: System.Classes.TCollectionNotification); override; public constructor Create; function Add: T; function FindItemID(ID: Integer): T; property Items[Index: Integer]: T read GetItem write SetItem; end; TRadioGroupItems = class(TItemCollection<TItem>); TRadioGroupBoxCollection = class(TGroupBox) private FColumns : Word; FValue : String; FIndexItem : Integer; FItems : TRadioGroupItems; CLayout : TGridLayout; procedure SetColumns(const Value: word); procedure SetValue(const Value: string); procedure Change(Sender : TObject); procedure SetIndexItem(const Value: Integer); procedure SetItems(const Value: TRadioGroupItems); protected function FindValue(const V : String) : Integer; procedure OnResize; public constructor Create(AOwner : TComponent); override; destructor Destroy; override; procedure AddItem(const Text : String; const Value : String); function Paint : Boolean; reintroduce; published property Items : TRadioGroupItems read FItems write SetItems; property Value : String read FValue write setValue; property IndexItem : Integer read FIndexItem write SetIndexItem; property Columns : word read FColumns write SetColumns stored Paint; end;
Génial, sauf que je n'arrive pas à faire le lien entre la modification des items et le dessin (ce qui au runtime se fait par addItem)
à mon avis cela se joue avec la procedure Notify de TItemCollection mais je ne vois pas comment accéder au AddItem du coup mon groupe radio n'affiche rien![]()
une idée ?
Partager