[Delphi 7] Hoe maak ik een groep van checkboxen

Pagina: 1
Acties:

  • EvdB
  • Registratie: November 2001
  • Laatst online: 13-05 19:53
Ik wil dus een visuele component zoals TRadioGroup maar dan met checkboxen. Via google heb ik weinig bruikbaars kunnen vinden, dus moet ik het zelf maar maken of iemand hier een oplossing voor mij.

  • andrew
  • Registratie: Februari 2001
  • Laatst online: 10-09-2024
Dit bestaat waarschijnlijk niet, omdat twee verschillende checkboxes normaliter niks met elkaar te maken hebben.

Maar als het alleen om het uiterlijk gaat kun je wel een TGroupBox maken met daarin TCheckBox componenten. Je zou hier ook zelf een klasse voor kunnen maken die TGroupBox extend.

  • FendtVario
  • Registratie: Januari 2002
  • Laatst online: 12-05-2025

FendtVario

The leader drives Vario!

Wat je kan doen om groepen te maken is alle checkboxen eenzelfde .tag waarde te geven. De onClick event laat je dan vervolgens naar een procedure verwijzen waarin je je actie uitvoert. Met de tag kun je dan alle checkboxen opzoeken die bij de groep horen.

( Of je zoek om Torry's of Delphi Super Page voor een componentje, vast wel een gek die dat ooit eens gemaakt heeft.)

www.fendt.com | Nikon D7100 | PS5


  • EvdB
  • Registratie: November 2001
  • Laatst online: 13-05 19:53
Ik heb het nu opgelost met een dxTreelist met daarin als eerste kolom een kolom met checkboxen.

@FendtVario: Bedankt voor de tag-tip, daar had ik nog niet aan gedacht, maar deze kan ik waarschijnlijk wel ergens anders voor gebruiken.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 00:07

Tomatoman

Fulltime prutser

EvdB schreef op donderdag 13 januari 2005 @ 15:20:
Ik heb het nu opgelost met een dxTreelist met daarin als eerste kolom een kolom met checkboxen.
Dat lijkt me niet bepaald een kostenefficiënte oplossing. dxTreeList deel maakt deel uit van ExpressQuantumTreeList, dat US$ 199,99 kost. Er zijn genoeg freeware oplossingen en je kunt ook zelf wat fabriceren. Neem gewoon een TRadioGroup en bouw die om naar een TCheckGroup. Een opzetje voor het idee:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class TCheckItem = class(TCollectionItem)
  ...
public
  property Checked: Boolean ...
  property State: TCheckBoxState ...
end;

class TCheckItems = class(TCollection)
  ...
end;

class TCheckGroup = class(TCustomGroupBox)
private
  FCheckboxes: TCheckItems;
  procedure SetCheckboxes(Value: TCheckItems);
published
  Checkboxes: TCheckItems read FCheckboxes write SetCheckboxes;
end;

procedure TCheckGroup. SetCheckboxes(Value: TCheckItems);
begin
  FCheckBoxes.Assign(Value);
end;
Het grote voordeel van een TCollection descendant voor de verschillende checkboxen is de design-time ondersteuning via de Object Inspector. Je kunt dan comfortabel de individuele checkboxen aan- en uitvinken.

Een goede grap mag vrienden kosten.


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Of gebruik de TCheckListBox van Delphi (pas vanaf D7?).

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

Nofi hoor, maar hoe moeilijk is het om zelf even iets in elkaar te zetten?

Het misbruiken van een TAG hiervoor, vind ik persoonlijk ronduit smerig, nofi.

Een TChecklistbox is niet echt wat je wilt, dat is een listbox waarin je checkjes kunt zetten.

Ik zou denk ik een eigen component maken. Die geef je 'de normale' public properties mee, zoals 'items' en 'itemindex'. Aan de hand van de waarde hiervan maak je checkboxes aan, en geeft die als onclick een procedure van je class mee waarin het juist zetten van de check en de itemindex geregeld wordt.

Ben je in nog geen 10 minuten mee klaar denk ik. Het maken van een component is minder moeilijk dan je denkt.

[ Voor 6% gewijzigd door Verwijderd op 14-01-2005 09:02 ]


  • FendtVario
  • Registratie: Januari 2002
  • Laatst online: 12-05-2025

FendtVario

The leader drives Vario!

Verwijderd schreef op vrijdag 14 januari 2005 @ 09:01:
Het misbruiken van een TAG hiervoor, vind ik persoonlijk ronduit smerig, nofi.

Ben je in nog geen 10 minuten mee klaar denk ik. Het maken van een component is minder moeilijk dan je denkt.
Wat vind jij wel geoorloofd gebruik van de tag property dan?

10 minuten lijkt me ook wat overdreven, misschien als je al een paar jaar niets anders doet dan componeten schrijven. Maar goed, je mag het een keer voordoen. Heeft de TS ook direct een oplossing. :P

www.fendt.com | Nikon D7100 | PS5


Verwijderd

Nou, na ongeveer 15 minuten prutsen heb ik dit:

Delphi:
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
unit test1;

interface

uses
  SysUtils, Classes, contnrs, stdctrls, dialogs, controls;

type
  TCheckGroup = class(TWinControl)
    procedure CheckboxOnClick(Sender: TObject);
    procedure ItemsOnChange(Sender: TObject);
  private
    FCheckBoxes: TObjectList;
    FItemindex: Integer;
    FItems: TStringlist;
    procedure SetItemindex(const Value: Integer);
    procedure SetItems(const Value: TStringlist);
  protected
    { Protected declarations }
  public
    constructor create(AOwner: TComponent); override;
    destructor destroy;override;
  published
    property Items: TStringlist read FItems write SetItems;
    property Itemindex: Integer read FItemindex write SetItemindex;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Standard', [TCheckGroup]);
end;

{ TCheckGroup }

constructor TCheckGroup.create(AOwner: TComponent);
begin
  FCheckBoxes:=TObjectlist.Create(true);
  FItems:=TStringlist.Create;
  FItems.OnChange:=ItemsOnChange;
  inherited;
end;

destructor TCheckGroup.destroy;
var
  nLus: Integer;
begin
  Items.Free;
  FCheckBoxes.Free;
  inherited;
end;



procedure TCheckGroup.ItemsOnChange(Sender: TObject);
var
  nLus: Integer;
  nTop: Integer;
  nWidth: Integer;
  oCheckBox: TCheckBox;
begin
 For nLus:=ControlCount-1 downto 0 do
   If Controls[nLus] is Tcheckbox then
     RemoveControl(Controls[nLus]);
 FCheckboxes.Free;
 FCheckboxes:=TObjectlist.Create(true);
 nTop:=0;
 nWidth:=0;
 For nLus:=0 to FITems.Count-1 do
   begin
     oCheckbox:=TCheckbox.Create(self);
     oCheckbox.Parent:=self;
     oCheckbox.Top:=nTop;
     nTop:=oCheckbox.Top+oCheckBox.Height+5;
     oCheckBox.Caption:=FItems[nLus];
     oCheckBox.OnClick:=CheckboxOnClick;
     If oCheckbox.Width>nWidth then
       nWidth:=oCheckBox.Width;
     FCheckboxes.Add(oCheckbox);
   end;
 FItemIndex:=-1;
 Height:=nTop;
 Width:=nWidth;
end;

procedure TCheckGroup.CheckboxOnClick(Sender: TObject);
var
  nLus: Integer;
begin
  If TCheckbox(Sender).Checked then
      begin
       If ItemIndex<>-1 then
         begin
           TCheckbox(FCheckboxes[ItemIndex]).OnClick:=NIL;
           TCheckbox(FCheckboxes[ItemIndex]).Checked:=False;
           TCheckbox(FCheckboxes[ItemIndex]).OnClick:=CheckboxOnClick;
         end;
       FItemindex:=FCheckboxes.IndexOf(Sender);
      end
    else
      FItemIndex:=-1;
end;

procedure TCheckGroup.SetItemindex(const Value: Integer);
var
  nLus: Integer;
begin
  If not (csLoading in ComponentState) then
    begin
      FItemindex := Value;
      For nLus:=0 to FCheckboxes.Count-1 do
        TCheckBox(FCheckboxes[nLus]).Checked:=False;
      If FItemIndex<>-1 then
        begin
          TCheckBox(FCheckboxes[FItemIndex]).OnClick:=Nil;
          TCheckBox(FCheckboxes[FItemIndex]).Checked:=True;
          TCheckBox(FCheckboxes[FItemIndex]).OnClick:=OnClick;
        end;
    end;
end;

procedure TCheckGroup.SetItems(const Value: TStringlist);
begin
  FItems.Assign(Value);
end;

end.


Zeker niet foutloos of af, en een schoonheidsprijs krijg je er ook niet direct voor, maar het basisgedrag is er al. Imo een 100% nettere oplossing dan werken met tag properties..

Dingen die er zeker nog aan verbeterd moeten worden, zijn:
• De itemindex property werkt nog niet helemaal lekker als ie designtime gezet wordt
• Resizen gaat nog niet goed
• de hoogte wordt nog niet helemaal netjes gezet

maar het basisidee werkt als de spreekwoordelijke tiet.

Wat betreft de tag property.. daar is eigenlijk geen geoorloofd gebruik voor imo..

//edit
wil je er een kadertje omheen, gebruik dan een panel of groupbox om van af te leiden, ipv. een twincontrol.

[ Voor 17% gewijzigd door Verwijderd op 14-01-2005 11:00 ]


Verwijderd

Verwijderd schreef op vrijdag 14 januari 2005 @ 10:46:
maar het basisidee werkt als de spreekwoordelijke tiet.

Wat betreft de tag property.. daar is eigenlijk geen geoorloofd gebruik voor imo..
Ik vind het hele idee eigenlijk `ill-conceived' (zoals dat in goed Nederlands heet).

Je hebt nu een TRadioGroup geprogrammeerd, maar dan met checkboxes. Dat vind ik een behoorlijk Slecht Idee™, omdat het uiterlijk van het component nu geen aanwijzing meer geeft over de functie ervan. De hele functie van checkboxes net is om niet opties aan te bieden die elkaar niet uitsluiten. Door af te wijken van user interface standaarden maak je je applicatie minder toegankelijk voor gebruikers -- alle ervaring die ze hebben met de functie en het gebruik van checkboxes in in één klap waardeloos geworden zodra ze dit component tegenkomen.

Dat is wel een beetje gedramatiseerd natuurlijk, maar feit blijft dat je niet moet proberen om de geijkte standaarden opnieuw te definiëren. Uiteindelijk schiet je daar alleen maar jezelf mee in de voet, omdat gebruikers een hekel zullen krijgen aan je programma.

Ik hoop dus dat dit niet is wat de TS wilde. Als de TS alleen maar een groepje checkboxes met een kader eromheen wilde[1], dan kan het component natuurlijk nog daarop aangepast worden (wordt het ook een stuk eenvoudiger van). Maar met het huidige gedrag is de gebruiker denk ik meer gediend met een gewone TRadioGroup.


[1] En dat is eigenlijk de essentie van het probleem: een checkbox groep is conceptueel niet erg nuttig, omdat de toestand van een enkele box toch de andere niet beïnvloed, of het nu binnen of buiten dezelfde "groep" zou zijn. Het kan eventueel voor de gebruiker wel nuttig zijn om boxes visueel te groeperen -- maar in dat geval is het voldoende om boxes die "bij elkaar horen" in een TGroupBox component te zetten, en dan ben je al klaar.

[ Voor 14% gewijzigd door Verwijderd op 14-01-2005 12:10 ]


Verwijderd

Verwijderd schreef op vrijdag 14 januari 2005 @ 12:07:
Je hebt nu een TRadioGroup geprogrammeerd, maar dan met checkboxes.
Eh.. dat is wat topicstarter vroeg:
Ik wil dus een visuele component zoals TRadioGroup maar dan met checkboxen.
Voor de rest ben ik het an sich met je eens, ik kan alleen niet zien waarom TS dit wil. Misschien is het in zijn applicatie wel iets wat logisch is, weet ik veel..

//edit
Het ging mij er om dat als je zoiets maakt, dat de weg die ik voorstel imo de weg is, itt. werken met tags bv.

[ Voor 61% gewijzigd door Verwijderd op 14-01-2005 12:13 ]


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 00:07

Tomatoman

Fulltime prutser

Verwijderd schreef op vrijdag 14 januari 2005 @ 12:10:
[...]

Eh.. dat is wat topicstarter vroeg:
[/quote]Ik vatte het eigenlijk op als een lijst met checkbox die het uiterlijk had van TRadioGroup. Je zou zo'n control dat bijvoorbeeld willen hebben omdat je heel vaak een lijstje met elkaar samenhangende opties in je programma gebruikt en je op deze manier geen gedoe hebt met het uitlijnen van de checkboxen. Het neemt niet weg dat je een rijtje checkboxen nooit mag gebruiken alsof het radio items zijn.

Lijstje radio items (er is maar 1 keuze mogelijk):
• Ik ben jonger dan 18 jaar.
• Ik ben 18 tot 24 jaar oud.
• Ik ben 25 tot 30 jaar oud.
• Ik ben ouder dan 30.

Lijstje checkboxen (er zijn 0 t/m 4 keuzes mogelijk):
• Ik ben jonger dan 18 jaar.
• Ik ben man.
• Ik ben programmeur.
• Ik gebruik checkboxen nooit als radio items.

Mocht je een lijstje zoals dit hebben:
• Ik ben jonger dan 18 jaar.
• Ik ben 18 jaar of ouder.
• Ik ben man.
dan doe je wat verkeerd. Dit lijstje is namelijk niet direct om te zetten in radio items óf checkboxen. Je moet daarom het lijstje anders opzetten. De eerste mogelijkheid is om er vier radio items van te maken die elkaar uitsluiten:
• Ik ben jonger dan 18 jaar en ik ben een man.
• Ik ben jonger dan 18 jaar en ik ben een vrouw.
• Ik ben 18 jaar of ouder en ik ben een man.
• Ik ben 18 jaar of ouder en ik ben een vrouw.
Een andere mogelijheid is dat je eerst een lijstje met 2 radio items neerzet:
• Ik ben jonger dan 18 jaar.
• Ik ben 18 jaar of ouder.
met daaronder een check box:
• Ik ben man.

Het is allemaal niet moeilijk, je moet alleen even logisch nadenken over hoe je je gebruikersinterface opzet.

Een goede grap mag vrienden kosten.


  • EvdB
  • Registratie: November 2001
  • Laatst online: 13-05 19:53
@ Tomatoman:
Ik ben toch al in het bezit van ExpressQuantumTreeList dus de kosten is geen probleem.

Ik wil een x aantal checkboxen toevoegen aan het formulier. De gegevens worden uit een stringlist gehaald. Deze checkboxen representeren dan de verschillende print formulieren. De gebruiker kan dan kiezen welke hij wel of niet kan printen.
Eerst had ik een radiogroup, maar dan kan de gebruiken slechts 1 formulier printen. Wanneer hij/zij er meer wil printen moet de handeling herhaald worden, vandaar de checkboxen.

Het werkt nu met een dxTreelist en ziet er ook netjes uit. Iedereen toch bedankt voor de moeite en de discussie, want ik heb er toch nog wat van geleerd.
Pagina: 1