![]() |
TVCheckListbox und TStringList
Hallo,
ich bin mit Delphi erst seit 8 Monaten am arbeiten, deshalb verzeiht meine Unwissenheit ;) Folgende Fragen: Was ist der Unterschied bei der TVCheckListbox zwischen
Delphi-Quellcode:
und
.Checked[i]
Delphi-Quellcode:
Wieso bringt mir
.State[i] = cbChecked
Delphi-Quellcode:
keinen Wert im Debuger?
myselection.Find(TCheckListbox(Sender).Items[i],myKat)
Wobei myselection eine interne Stringlist ist und der Event OnClickCheck einer Checklistbox im Form ausgelöst wurde. Meine Intention ist, aus einer Checklistbox in einem Formular die markierten Einträge in einer internen Stringlist zu sammeln um sie anschließend in der DB zu speichern bzw.zu löschen. Irgendwie gelingt mir das nicht, die Liste aktuell zu halten hier mein Versuch:
Delphi-Quellcode:
Was mach ich falsch?
begin
myLst:= TCheckListbox(Sender).Name; if not assigned(myselection) then myselection := TStringList.create; //myselection.clear beim speichern begin myselection.Sort; TCheckListbox(Sender).Sorted := True; for i := TCheckListbox(Sender).Count-1 downto 0 do // if TCheckListbox(Sender).Checked[i] then if TCheckListbox(Sender).State[i] = cbChecked then begin if not (myselection.Find(TCheckListbox(Sender).Items[i],myKat)) then myselection.Add(TCheckListbox(Sender).Items[i]); end else if (myselection.Find(TCheckListbox(Sender).Items[i],myKat)) and (TCheckListbox(Sender).State[i] = cbUnChecked) then myselection.Delete(TCheckListbox(Sender).ItemIndex); end; end; |
AW: TVCheckListbox und TStringList
Hat jetzt nichts direkt mit deinem Problem zu tun, aber ein paar Tipps zu deinem Code.
Das Erstellen der StringList innerhalb der Prozedur ist ungünstig, denn wo woird sie wieder frei gegeben? Ich fürchte, es ist eine globale Variable. Nicht schön. Erstelle die StringList in der aufrufenden Prozedure, über gib sie als Parameter und gib sie in der aufrufenden Prozedure wieder frei. Warum arbeitest du mit dem Objekt Sender? Deine Routine sollte in einer Procedure liegen, die nichts mit den Steuerelementen zu tun hat:
Delphi-Quellcode:
Das hilft auch bei der Fehlersuche.
Procedure DeleteCheckedItems(ChecklistBox: TVCheckListbox; MySelection: TStringList);
begin ...; ...; end; Setz mal einen Haltepunkt mit F5 bei der ersten Anweisung und dann geh mal mit F7 Schritt für Schritt durch den Code. Springt er überhaupt in die Verzweiung? |
AW: TVCheckListbox und TStringList
Zitat:
Am Ende wird beim speichern die Liste wieder freigegeben. Meine Fragen wurden leider noch nicht beantwortet. Gruß BP |
AW: TVCheckListbox und TStringList
Hast du es denn inzwischen mal debuggt, wie beschrieben?
Ich würde dazu eine separate Schaltfläche benutzen. Das wird den Benutzer wohl auch weniger verwirren, nichts passiert während er noch mit der Listbox zu Gange ist. |
AW: TVCheckListbox und TStringList
Zitat:
Ich werd beim debuggen nicht schlau. Und ja, ich habe früher in anderen Umgebungen schon entwickelt. Ist mein Vorgehen in einer OO-Architektur so absonderlich? P.S.: Bin ich vielleicht in der falschen Ecke? Dann bitte verschieben. |
AW: TVCheckListbox und TStringList
Warum wirst du beim debuggen nicht schlau? Wurde der Code denn nach deinen Vorstellungen ausgeführt?
|
Dieses Thema wurde am "06. Jul 2019, 22:18 Uhr" von "Luckie" aus dem Forum "Programmieren allgemein" in das Forum "GUI-Design mit VCL / FireMonkey / Common Controls" verschoben.
|
AW: TVCheckListbox und TStringList
Zitat:
|
AW: TVCheckListbox und TStringList
Wie lautet denn der Rückabewert und was steht nachher in Muskat für ein Index?
|
AW: TVCheckListbox und TStringList
Was meinst du mit
Zitat:
Der Rückgabewert sollte Bool sein, der Debuger zeigt mir aber nichts:shock: |
AW: TVCheckListbox und TStringList
myKat
Wie soll er auch was anzeigen, wenn du keine Variable zu weist? Aber geht er denn in den if-Zweig rein? |
AW: TVCheckListbox und TStringList
Also, der Find funktioniert auch wenn er den Wert des Ausdrucks nicht anzeigt ('Nicht verfügbarer Wert'), wieso weshalb wissen die Delphi-Götter;)
Die andere Frage beantworte ich mir selbst, sie agieren identisch. Das Problem lag woanders, der gezeigte Code erfüllt allerdings noch nicht mein Vorhaben. |
AW: TVCheckListbox und TStringList
Zitat:
2. myselection ist wohl ein Feld deiner Form. Richtig? Versuche dich an di gängigen Namen/Formatregeln von Delphi anzupassen, damit die Wartung deinss Programms später mal einfacher wird. Verwende daher für Object-Felder das Format Fxxx. (FMySelection würde ich es nennen) So siehst du sofort im Code, dass das eine Object-Feldvariable ist. 3. Abfage auf Checked reicht hier, wenn deine Checkboxen nur True/False haben können. Wenn du noch den 3. Status (grayed) hast, wirst du State abfragen müssen. Soweit die Antwort wieso es Checked und State gibt. 4. Wenn du nur ein Clear beim Speichern machst, fehlt dir noch ein Free der Stringliste irgendwo. Das gehört in das OnDestroy Event der Form oder noch besser in einen überschriebenen Destructor deiner Form. Habe dir mal den Code so angepasst, wie ich das machen würde:
Delphi-Quellcode:
var
StrIdx: Integer; begin // myLst:= TCheckListbox(Sender).Name; ??? if not Assigned(FMySelection) then FMySelection := TStringList.Create; //FMySelection.clear beim speichern // begin <- unnötig! //myselection.Sort; // wofür? //TCheckListbox(Sender).Sorted := True; // wofür? for i := 0 to TCheckListbox(Sender).Count-1 do begin StrIdx := FMySelection.IndexOf(TCheckListbox(Sender).Items[i]); if TCheckListbox(Sender).Checked[i] then begin if StrIdx = -1 then // Text nicht vorhanden FMySelection.Add(TCheckListbox(Sender).Items[i]); end // Checked muss hier nicht abgefragt werden, da das durch das if/else bereits geregelt ist. else if (StrIdx <> -1) then begin FMySelection.Delete(StrIdx); end; end; end; |
AW: TVCheckListbox und TStringList
Zitat:
Zitat:
Delphi-Quellcode:
var
myCheckLst : TCheckListbox; myLst : String; myKat : Integer; begin if Sender is TCheckListbox then begin myCheckLst := TCheckListbox(Sender); myLst := myCheckLst.Name; // Wird das für irgendwas benötigt? // Bitte Luckies Kommentar dazu beachten und entsprechend umsetzen. if not assigned(myselection) then myselection := TStringList.create; // myselection.clear beim speichern myselection.Sort; myCheckLst.Sorted := True; for i := myCheckLst.Count - 1 downto 0 do begin if myCheckLst.Checked then begin if not (myselection.Find(myCheckLst.Items[i],myKat)) then myselection.Add(myCheckLst.Items[i]); end else begin // Wir suchen also in myselection die Zeichenfolge aus Items[i] if myselection.Find(myCheckLst.Items[i],myKat) then begin // und wenn wir die gefunden haben, löschen wir in myselection den Eintrag, // der die Position in myselection hat, die dem aktuell ausgewählten Eintrag aus myCheckLst entspricht? // Das ist dann so eine Art Zufallsgenerator, aber bestimmt nicht im Sinne des Erfinders. // myselection.Delete(myCheckLst.ItemIndex); // Könnte da nicht eher dashier zielführend sein, schließlich haben wir das ja gerade per Find ermittelt? myselection.Delete(myKat); end; end; end; end; end else begin // Sinnvolle Fehlermeldung ausgeben, wenn das Ereignis für was anderes als 'ne TCheckListbox aufgerufen wird. end; end; |
AW: TVCheckListbox und TStringList
Noch eine Ergänzung:
Wieso willst du diese Liste ständig aktuell halten, wenn du sie nur beim Speichern benötigst? Es würde doch reichen, die Liste jeweils komplett neu zu laden, also am Anfang ein Clear und dann eine simple for/next Schlaufe. Du machst dir da das Leben irgendwie viel zu umständlich. Es gibt keinen Grund die Liste zu bearbeiten. Das ganze würde wohl sogar um einiges schneller ablaufen, wenn du da keine Suchoperationen nutzen musst. Also mach doch einfach das oder gib soagr ein Resultat retour, das du dann 1:1 direkt in die DB schreiben kannst, ohne dass du beim Speichern noch die StringList verarbeten musst:
Delphi-Quellcode:
procedure TForm1.FillMySelection(const ACheckListbox: TCheckListbox);
var StrIdx: Integer; begin if not Assigned(FMySelection) then FMySelection := TStringList.Create else FMySelection.Clear; for i := 0 to ACheckListbox.Count-1 do if ACheckListbox.Checked[i] then FMySelection.Add(ACheckListbox.Items[i]); end; |
AW: TVCheckListbox und TStringList
Zitat:
Deinen Gedanken hatte ich auch schon, das Problem ist, dass die Daten aus einer Abfrage auf 6 Listenfelder anhand von Ausprägungen verteilt werden. Ich möchte auch die Einträge in der Tabelle nicht bei jeder Änderung Löschen und neu anlegen sondern nur gelöschte entfernen und neue hinzufügen. Daher die Idee mit der aktualisierten Liste. @Delphi.Narium & @Rolf Frei Danke für das lösen meines Knotens und die Empfehlungen, auf sowas habe ich gehofft;) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:58 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz