Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - Zwei Checkboxen in Checklistbox verbinden
Kralle - Fr 22.07.11 23:59
Titel: Zwei Checkboxen in Checklistbox verbinden
Guten Abend,
ich möchte, das wenn ich in einer CheckListBox einen Eintrag abwähle auch ein zweiter abgewählt wird.
Ich habe das so probiert:
Delphi-Quelltext
1: 2: 3:
| CLB_middle.Checked[zeilennr2] := CLB_middle.Checked[zeilennr];
CLB_middle.Checked[zeilennr] := CLB_middle.Checked[zeilennr2]; |
Aber die Checkboxen reagieren nur auf die oberste Zeile.
Wichtig ist aber, das egal ob Zeile 1 oder Zeile 2 abgewählt wird, die andere auch abgewählt wird.
Ich habe es auch mit
Delphi-Quelltext
1: 2: 3: 4:
| If CLB_middle.Checked[zeilennr] = false then CLB_middle.Checked[zeilennr2] := false; If CLB_middle.Checked[zeilennr2] = false then CLB_middle.Checked[zeilennr] := false; |
probiert, aber dann ist nach dem ersten abwählen Schluß und ich kann die Zeilen nicht mehr anwählen.
Was übersehe ich um diese Uhrzeit?
Gruß Heiko
jaenicke - Sa 23.07.11 10:25
Kralle hat folgendes geschrieben : |
Ich habe das so probiert:
Delphi-Quelltext 1: 2: 3:
| CLB_middle.Checked[zeilennr2] := CLB_middle.Checked[zeilennr];
CLB_middle.Checked[zeilennr] := CLB_middle.Checked[zeilennr2]; |
Aber die Checkboxen reagieren nur auf die oberste Zeile. |
Naja, zuerst wird die erste Zeile ausgeführt. Danach ist der Status der ersten in der zweiten drin.
Wenn dann die zweite Zeile ausgeführt wird, wird dieser Wert nur in die erste zurückgelegt...
Kralle hat folgendes geschrieben : |
probiert, aber dann ist nach dem ersten abwählen Schluß und ich kann die Zeilen nicht mehr anwählen.
|
Naja, irgendwie musst du ja auch erst einmal einen einzeln aktivieren können. Mit deinem Code deaktivierst du schon den ersten sofort wieder.
Das Problem ist hier, dass du die Daten (was markiert ist) mit der Oberfläche durcheinanderwirfst. Denn so weißt du nicht welcher Eintrag geändert wurde. Wenn du aber bei einer Änderung abgleichst, was sich geändert hat, kannst du nur beim Abwählen den zweiten mitnehmen und ein Anwählen erlauben.
Oder du benutzt eine ordentliche Komponente wie die
TVirtualStringTree [
http://www.delphi-gems.com/index.php?option=com_content&task=view&id=12&Itemid=38], da gibt es das Ereigbnis OnChecking, in dem du das Markieren sogar direkt unterbinden kannst usw., aber vor allem bekommst du geliefert was sich eigentlich genau ändert. Also welcher Eintrag, ob er an- oder abgewählt wird, ...
Und danach in OnChecked bekommst du den Knoten ebenfalls geliefert.
Xion - Sa 23.07.11 13:43
Hab mir eben mal den Code von der CheckListBox angeguckt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| procedure TCheckListBox.ToggleClickCheck(Index: Integer); var State: TCheckBoxState; begin if (Index >= 0) and (Index < Items.Count) and GetItemEnabled(Index) then begin State := Self.State[Index]; case State of cbUnchecked: if AllowGrayed then State := cbGrayed else State := cbChecked; cbChecked: State := cbUnchecked; cbGrayed: State := cbChecked; end; Self.State[Index] := State; ClickCheck; end; end;
procedure TCheckListBox.ClickCheck; begin if Assigned(FOnClickCheck) then FOnClickCheck(Self); end; |
Ich frage mich warum der Entwickler den Index nicht mit nach außen gereicht hat, da es wirklich naheliegend und einfach wäre... Leider ist Toggle private...man müsste also an die original-Datei ran und dort ändern, dann wirkt es sich aber auf ALLE deine Projekte aus
Edit:
Was man noch verantworten könnte, wäre das Toggle als protected zu setzen und dann davon zu erben, die Methode zu überschreiben und ein zusätzliches Event zu erstellen. Dann kannst du aber diese Klasse nur compilieren, wenn du die modifizierte Originaldatei hast (Problem nach Neuinstallation, fremden Rechner)...nicht wirklich schön.
Edit2:
Vielleicht wäre es doch am einfachsten/saubersten dir bei jedem OnClickCheck die zwei Werte, die dich interessieren, zwischenzuspeichern und beim nächsten mal zu gucken, welches sich verändert hat und das entsprechend andere zu setzen. Ein bool Array wäre da ja völlig ausreichend (als Gegenstück zu CheckListBox.Checked[]).
Kralle - Sa 23.07.11 14:45
Moin,
Xion hat folgendes geschrieben : |
Edit2:
Vielleicht wäre es doch am einfachsten/saubersten dir bei jedem OnClickCheck die zwei Werte, die dich interessieren, zwischenzuspeichern und beim nächsten mal zu gucken, welches sich verändert hat und das entsprechend andere zu setzen. Ein bool Array wäre da ja völlig ausreichend (als Gegenstück zu CheckListBox.Checked[]). |
Das werde ich mal testen.
Danke, das Du Dir soviel Mühe gemacht hast und sogar den Quellcode der Orginalroutine nach einer Möglichkeit untersucht hast.
Gruß Heiko
jaenicke - Sa 23.07.11 14:46
Aber wie gesagt: Die TVirtualStringTree kann viel mehr und liefert dir die Informationen auch direkt. Also warum nicht gleich die benutzen? :nixweiss:
Kralle - Sa 23.07.11 14:47
Hallo Sebastian,
jaenicke hat folgendes geschrieben : |
Das Problem ist hier, dass du die Daten (was markiert ist) mit der Oberfläche durcheinanderwirfst. Denn so weißt du nicht welcher Eintrag geändert wurde. Wenn du aber bei einer Änderung abgleichst, was sich geändert hat, kannst du nur beim Abwählen den zweiten mitnehmen und ein Anwählen erlauben.
Oder du benutzt eine ordentliche Komponente wie die [url]TVirtualStringTree[/url], da gibt es das Ereigbnis OnChecking, in dem du das Markieren sogar direkt unterbinden kannst usw., aber vor allem bekommst du geliefert was sich eigentlich genau ändert. Also welcher Eintrag, ob er an- oder abgewählt wird, ...
Und danach in OnChecked bekommst du den Knoten ebenfalls geliefert. |
Ich werde mir die Tage mal die obige Komponente anschauen (Dein Link funktioniert nicht).
Gruß Heiko
Kralle - Mo 25.07.11 07:36
Moin,
Das ist aber ja eine Komponente um z.B. Verzeichnisbäume anzuzeigen.
Ich brauche nur eine Liste in der ich Einträge an- und abwählen kann.
Gruß Heiko
jaenicke - Mo 25.07.11 09:54
Kralle hat folgendes geschrieben : |
Das ist aber ja eine Komponente um z.B. Verzeichnisbäume anzuzeigen.
Ich brauche nur eine Liste in der ich Einträge an- und abwählen kann. |
Das kann die Komponente genauso gut. Das ist quasi die tabellenlegende Baumknotensau. :mrgreen:
Kralle - Di 09.08.11 20:05
Moin,
jaenicke hat folgendes geschrieben : |
| Das kann die Komponente genauso gut. Das ist quasi die tabellenlegende Baumknotensau. :mrgreen: |
Ich habe mir die Anleitung durch gelesen und entschieden, das ich das für aktuelle Projekt erstmal nicht einsetzen werde.
Die Links werde ich mir aber bei Seite packen und vielleicht in der nächsten Ausbaustufe des Programmes darauf zurückkommen.
Danke, für die Hilfe.
Gruß Heiko
Delphi-Laie - Mi 10.08.11 16:30
Kralle hat folgendes geschrieben : |
Ich habe es auch mit
Delphi-Quelltext 1: 2: 3: 4:
| If CLB_middle.Checked[zeilennr] = false then CLB_middle.Checked[zeilennr2] := false; If CLB_middle.Checked[zeilennr2] = false then CLB_middle.Checked[zeilennr] := false; |
probiert, aber dann ist nach dem ersten abwählen Schluß und ich kann die Zeilen nicht mehr anwählen. |
Einen Wahrheitswert auf false zu prüfen, ist zwar logisch nicht falsch, aber unelegant und wegen Compiler-Interna sogar in gewisser Weise falsch, (soll tatsächlich zu falschen Ergebnissen führen können) auch wenn der Fehler oder "Fehler" m.E. eindeutig beim Compiler liegt (interne Verarbeitung logischer Werte über Integervariablen). Dazu gab es schon Diskussionen. Eleganter und kürzer ist jedenfalls einfach:
if not ...
jaenicke - Mi 10.08.11 16:49
Delphi-Laie hat folgendes geschrieben : |
| Einen Wahrheitswert auf false zu prüfen, ist zwar logisch nicht falsch, aber unelegant und wegen Compiler-Interna sogar in gewisser Weise falsch, (soll tatsächlich zu falschen Ergebnissen führen können) |
Der Vergleich mit False wird nicht fehlschlagen, da False tatsächlich immer gleich Null ist. Da alles andere aber als True gilt, egal welcher Wert, kann der Vergleich mit True fehlschlagen.
Hier habe ich mal ein kleines Beispiel gebastelt, wann es schief geht:
http://www.delphi-forum.de/viewtopic.php?p=548760#548760
Mehr dazu steht hier:
http://www.delphi-treff.de/tutorials/objectpascal/programmierung-mit-boolean-werten/page/4/
Und warum das auch vollkommen unlogisch ist:
http://www.delphi-forum.de/viewtopic.php?p=560637#560637
Delphi-Laie hat folgendes geschrieben : |
| auch wenn der Fehler oder "Fehler" m.E. eindeutig beim Compiler liegt (interne Verarbeitung logischer Werte über Integervariablen) |
True und False sind nur Konstanten für einen Wert. Wenn du damit vergleichst, kann da der Compiler doch nichts dafür, wenn das nicht das ist was du wolltest. ;-)
Man kann Programmierfehler eben nicht sinnvoll durch Compilermagic ausgleichen, da sonst der zusätzliche Code alles signifikant langsamer machen würde. Man könnte höchstens Warnungen einbauen oder so. Allerdings steht dieser Fehler nicht umsonst unter "Anfängerfehler" in diversen Tutorials usw. :zwinker:
Aber zu dem Thema gibt es in der Tat bereits genug Threads. :D
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!