ComboBox - OnChange Problem
-
Hi,
in meinem Programm, verwende ich eine ComboxBox. Mittels dem OnChange Problem, überprüfe ich, ob der Benutzer den akutellen Wert ändert. Anschließend wird eine längere Berechnung durchgeführt und eine andere ComboBox bekommt errechnete Werte.
Jetzt habe mir einmal die Werte errechnen kann und wähle in der ersten ComboxBox mit der Maus noch mal genau den Wert aus, der bereits markiert ist.
Was mich stört ist, dass die Berechnung neu durchgeführt ist, obwohl sich der Wert in der ersten ComboxBox gar nicht geändert hat.
Wieso heißt die Eigenschaft dann OnChange wenn sich nichts geändert hat?
Wie kann ich vorher überprüfen, ob sich der Wert nun tatsächlich geändert hat?
mark
-
Eigentlich recht simpel: merk Dir, wenn Du im OnChange Ereignis die Berechnung vornimmst (bzw. vornehemen läßt), einfach den Wert der Eigenschaft ItemIndex in einer Klassenvariablen (am günstigsten als private deklariert).
Beim nächsten Aufruf von OnChange vergleichst Du diesen Wert mit ItemIndex. Hat sich nichts geändert, machste ein return und gut ist.
Natürlich mußt Du im Konstruktur in der Klassenvariablen einen Wert reinschreiben, der nicht in der ComboBox vorkommen kann. Z.B. 0xFFFFFFFF. Dann wird OnChange richtig funzen.
-
Original erstellt von JFK:
machste ein return und gut istDas wäre aber nicht wirklich gut, zumindest kein guter Stil.
Warum nicht die Abfrage so formulieren, dass sie bei übereinstimmenden Werten einfach nichts macht?if (a != b) { berechne(); } //else //{ // mach_was_anderes(); //} // oder eben gar nichts
Mark M.
OnChange heisst, dass sich irgendwas an der ComboBox geändert hat, und das ist duch das (erneute) Selektieren des Eintrages geschehen, der Inhalt des Eintrages könnte sich ja inzwischen geändert haben. Du musst also entweder selbst darauf achten, welche Werte zuletzt angezeigt wurden, oder du leitest eine Komponente von TComboBox ab und erweiterst sie um die entsprechende "Aufpasser"-Funktionalität.
-
@Jansen: haste recht. Aber in größeren Konstruktionen bietet es sich an, gleich zu "offenbaren", daß nix mehr passiert. Wenn man viel if's und Schleifen hat, wird man sonst auch manchmal etwas "närrisch".
Ich bin da eher für klare und schnell ersichtliche Wege....
-
Ein unnötiges return ist verdammt nahe an goto ...
-
Hallo Jansen,
die Idee finde ich gut, weiß aber nicht wie ich dies realisieren soll:
if (a != b) { berechne(); }
Ich würde einfach den ItemIndex vergleichen. Die Frage ist nur, ich brauche ja den alten ItemIndex und den neuen. Wie komme ich denn an dann an den alten?
Mark
-
Du solltest eben nicht den ItemIndex vergleichen sonden den tatsächlich angezeigten Wert. Zum einen kann sich ja, wie gesagt, theoretisch der Wert des Items geändert haben, zum anderen sollte deine Prüfung möglichst universell sein und auch das eventuelle manuelle Ändern des CB-Textes abfangen.
Also einfach den CB-Text immer in einer Variablen zwischenspeichern (siehe JFK) und im OnChange den aktuellen Wert mit dem gespeicherten vergleichen. Und nicht vergessen, den geänderten Text dann auch wieder in die Zusatzvariable zu schreiben.
PS.
Prinzipiell kannst du es natürlich auch über den ItemIndex machen. Den alten Index holst du dir einmal zum Programmstart und den neuen alten dann jeweils auch im OnChange.[ Dieser Beitrag wurde am 27.06.2003 um 22:07 Uhr von Jansen editiert. ]
-
Hab ich doch oben geschrieben? Leg ne private Variable an, die den jeweils vorherigen Wert enthält....
im Konstruktor: a = 0xFFFFFFFF // Wert kommt nie in ComboBox vor
in OnChange:
if (a != TComboBox->ItemIndex){ a = TComboBox->ItemIndex; // aktuellen Wert für's nächste Mal merken berechne(); // rechne mal schön... else // mach nix
Na und nu rechnet er nur bei einer echten Änderung. Eigentlich ganz easy.
@Jansen: das mit dem goto kann ich nicht ganz nachvollziehen. Wenn ich die break Anweisung in Schleifen verwende, mach ich im Prinzip auch nix anderes (nur auf Block- und nicht auf Methodenebene). Klar könnte man das auch mit goto erreichen, aber davon is return doch noch ein bißchen entfernt...?
Vermutlich störst Du Dich eher dran, daß es mehrere Methoden-Ausgänge gibt?
Aber wie machst Du das bei Fehlerbehandlungen? Wenn Du in einer Methode 20 mal auf Fehlerwerte prüfen mußt, dann gehts nich mehr ganz so einfach nach Deiner Lösung und man muß ggf. mit Hilfswerten arbeiten. Ob das verständlicher, performanter und einfacher ist, waage ich eher zu bezweifeln...?Fehlerflag = FALSE; <Aufruf von irgendwas> if(Fehler){ <Fehlerbehandlung> Fehlerflag = TRUE } if (!Fehlerflag){ <Aufruf von irgendwas> if(Fehler){ <Fehlerbehandlung> Fehlerflag = TRUE } else <mach sonstwas> } if (!Fehlerflag){ <Aufruf von irgendwas> if(Fehler){ <Fehlerbehandlung> Fehlerflag = TRUE } else <mach sonstwas> } ....
???
-
Original erstellt von JFK:
Wenn ich die break Anweisung in Schleifen verwende, mach ich im Prinzip auch nix anderes (nur auf Block- und nicht auf Methodenebene)."Normalerweise" beendet man eine Schleife ja auch nicht mit break, sondern indem man die Abbruchbedingung wahr werden lässt.
for (int i = 0; i < ganz_viel; i++) { machwas(); if (abbruchsignal == true) i = ganz_viel; }
Aber lass uns das nicht weiter vertiefen, ist doch schon ziemlich offtopic. Bei Bedarf kannst du es ja mal in "Rund um" zur Diskussion stellen.