Witam. Stworzyłem sobie prosty programik który dodaje 2 liczby z pola edit1 i edit2, a następnie po klknięciu buttona wyświetla wynik w edit3. W jaki sposób zmodyfikować kod aby wynik był od razy wyświetlany bez konieczności klikania buttona?
Oprogramuj zdarzenia OnChange
dwóch pól edycyjnych, w których wpisuje się dwie liczby (a najlepiej oprogramuj jedno i podepnij do drugiego); Konwersji liczb dokonuj funkcją TryStrToInt, aby program nie rzucał wyjątków; Jeśli funkcja dla dwóch editów zwróci True to wpisz wynik w polu trzecim (czyli dokonaj odwrotnej konwersji za pomocą IntToStr); Jeśli konwersja nie powiedzie się (bo np. jedno pole jest puste) to czyść to trzecie pole;
Szablon:
if TryStrToInt(Edit1.Text, intA) and TryStrToInt(Edit2.Text, intB) then
// ustaw wynik w Edit3
else
// wyczyść Edit3
Tyle filozofii; Wątek dotyczy podstaw programowania, więc przenoszę go do odpowiedniego działu.
Jestem laikiem w programowaniu i posiadam wiedzę teoretyczną i ciężko póki co przełożyć to na praktyczną. Dlatego proszę o wyjaśnienie jak mniej więcej powinno to wyglądać.
Stworzyłem sobie 3 pola edit. W edit1 i edit2 mam podać 2 liczby, a w edit3 ma pojawić się wynik.
wygląda to mniej więcej tak:
var
A,B:integer;
begin
if TryStrToInt(Edit1.Text, intA) and TryStrToInt(Edit2.Text, intB) then
Edit3.text:=(A+B);
else
ShowMessage('Error')
end;
end.
Przecież wyżej masz odpowiedź jak to dokładnie ma wyglądać. Gotowca nie dostaniesz.
@aro.cfc - prawie dobrze, ale wolałeś napisać po swojemu, czego rezultatem jest niekompilujący się kod;
Po pierwsze zadeklarowałeś zmienne, których nie używasz w wywołaniach funkcji TryStrToInt, czyli przy kompilacji dostaniesz błędy; Najpierw zadeklaruj porządnie zmienne i używaj ich w dalszej części:
var
intA, intB: Integer;
Następnie trzeba zapisać warunek, który dokona konwersji wartości z obu pól edycyjnych, a korzystając z koniunkcji zapewniamy sobie tylko jeden przypadek, gdy będziemy ustalać wynik wyjściowy (obie wartości da się przekonwertować na liczby); Zapis takiego warunku podałem wcześniej:
if TryStrToInt(Edit1.Text, intA) and TryStrToInt(Edit2.Text, intB) then
Teraz co mamy zrobić, kiedy konwersja powiedzie się; Otóż sumę liczb musimy wpisać do pola Edit3
, czyli użyć zmiennych intA
i intB
, zesumować je, a wynik wpisać do pola Edit3
, używając funkcji IntToStr; Musimy to zrobić, bo wynik jest liczbą, a zawartość pola edycyjnego to tekst; Czyli należy wpisać do pola sumę w ten sposób:
Edit3.Text := IntToStr(intA + intB)
A co ma się stać, jeśli konwersja nie powiedzie się? Pole edycyjne należy wyczyścić, aby usunąć poprzednią jego zawartość; Dlatego też po Else należy tylko i wyłącznie wywołać metodę czyszczącą zawartość w trzecim polu:
Edit3.Clear();
Rezultatem działania tego kodu będzie pokazywanie na bieżąco sumy liczb z dwóch pierwszych pól edycyjnych; Jeśli oba pola są puste, jedno z nich jest puste lub wartość któregokolwiek pola nie może być przekonwertowana - trzecie pole będzie puste;
Cały kod należy zawrzeć w zdarzeniu OnChange
pierwszego pola:
procedure TForm1.Edit1Change(Sender: TObject);
var
intA, intB: Integer;
begin
if TryStrToInt(Edit1.Text, intA) and TryStrToInt(Edit2.Text, intB) then
Edit3.Text := IntToStr(intA + intB)
else
Edit3.Clear();
end;
W oknie Inspektora Obiektów ustawiasz zdarzenie OnChange
dla drugiego pola takie samo, jak dla pierwszego; Dzięki temu oba pola edycyjne będą korzystać z jednego kodu, zamiast pisać dwa razy to samo (zasada DRY); Trzeciemu polu możesz ustawić właściwość ReadOnly
na True, aby służyło jedynie do wyświetlania tekstu, bez możliwości modyfikacji wyniku sumowania;
To tyle - program działa jak należy i nie powoduje rzucania wyjątków;
Co ciekawe, w dwóch pierwszych polach możesz podawać liczby w różnych systemach zapisu liczb, nie tylko w dziesiętnym - przynajmniej w Lazarusie; Już tłumaczę dlaczego; Funkcja TryStrToInt wewnętrznie korzysta z procedury Val, która to potrafi konwertować liczby zapisane w systemie dziesiętnym, ale także w systemach:
-
heksadecymalnym - dla dodatnich liczb dozwolone są prefiksy
0x
,+0x
,$
oraz+$
, dla ujemnych-0x
oraz-$
, -
oktalnym - dla dodatnich prefiks
&
lub+&
, dla ujemnych-&
, -
binarnym - i tak samo, dla dodatnich liczb prefiks
%
lub+%
, dla ujemnych-%
;
Inne systemy zapisu liczb, które są obsługiwane przez funkcje konwersji z RTL nie są mi znane i raczej nie są obsługiwane; W każdym razie program jest bajecznie prosty, dosłownie kilka linii kodu, a daje całkiem fajne możliwości, o których pewnie niejeden nie miałby pojęcia;
Ale to tak w ramach ciekawostki; Ostatnio dość dużo czasu poświęciłem na optymalizację funkcji konwersji w mojej bibliotece do obsługi konfiguracji TreeStructInfo, w której wszystkie cztery wymienione systemy zapisu są obsługiwane; Tyle że dla liczb szesnastkowych przewidziany jest prefiks [+/-]0x
, dla ósemkowych [+/-]0o
, a dla dwójkowych [+/-]0b
.
Dzięki bardzo za tak obszerne wytłumaczenie. Przynajmniej sie nie zniechęcam i jadę dalej na tym wózku. Teraz zmienię sobie typ danych, żeby zliczało też liczby z przecinkiem.
Jedna rzecz mnie zastanawia dlaczego musi to akurat być w zdarzeniu OnChange.
No bo jak inaczej program ma wiedzieć, że wpisałeś coś do edita? Albo przez kliknięcie buttona (którego chcesz uniknąć) albo przez inne zdarzenia. Możesz to jeszcze ewentualnie umieścić w OnKeyPress ale OnChange jest, hmmm, logiczniejsze.
aro.cfc napisał(a)
Jedna rzecz mnie zastanawia dlaczego musi to akurat być w zdarzeniu OnChange.
Zdarzenie OnChange
wywoływane jest za każdym razem, gdy wartość pola edycyjnego zmienia się - czyli po np. dodaniu znaku, jego odjęciu, usunięciu podciągu, wyczyszczeniu wartości czy nawet po operacjach z użyciem schowka (wytnij, wklej itd.); Dlatego też jest to najodpowiedniejsze zdarzenie do tego, aby odświeżać wartość pola z wynikiem;
Teraz zmienię sobie typ danych, żeby zliczało też liczby z przecinkiem.
Wystarczy zamienić typy zmiennych z Integer na Double, wywołania funkcji TryStrToInt na TryStrToFloat oraz do sformatownia wyniku skorzystać z funkcji FloatToStr (lub bogatszą w argumenty FloatToStrF) lub po prostu Format.
Dzięki za obszerne wyjaśnienie.