Wątek przeniesiony 2015-09-14 01:46 z Delphi i Pascal przez furious programming.

Wyświetlanie wyniku po wprowadzeniu danych

0

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?

2

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.

0

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.
1

Przecież wyżej masz odpowiedź jak to dokładnie ma wyglądać. Gotowca nie dostaniesz.

1

@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.

0

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.

1

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.

3
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.

0

Dzięki za obszerne wyjaśnienie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1