Kontrolki i Kalkulator

Z Zasoby CoderDojo
Skocz do: nawigacji, wyszukiwania

UWAGA: Ten scenariusz do poprawnego działania wymaga dodatkowych komponentów - kontrolek. Aby móc wykonać zadania z poniższego scenariusza należy wykorzystać specjalną wersję Greenfoot’a przygotowaną dla Mistrzów Kodowania.

Poziom I: Przyciski i wyświetlacz

Omówienie zadania:

Pierwszy poziom skupi się na stworzeniu świata, przycisków numerycznych i funkcyjnych:

  • Świat - standardowo, pierwszy krok w tworzeniu aplikacji za pomocą Greenfoot’a.
  • Dodanie przycisków numerycznych.
  • Dodanie przycisków funkcyjnych.
  • Dodanie wyświetlacza.

Realizacja zadania:

Stworzenie świata

W ogólnym rozumieniu świat w Greenfoot’cie jest miejscem, gdzie działać będą zakodowane przez nas algorytmy i gdzie będą istnieć stworzone przez nas obiekty. W rozumieniu technicznym świat jest po prostu klasą Javy, która dziedziczy z klasy World (poprzez dziedziczenie rozumiemy pewien szczególny przypadek klasy World). Światem dla aplikacji kalkulator będzie klasa Kalkulator. Za takim wyborem przemawia fakt, że do świata dodaje się aktorów. Do kalkulatora dodamy więc przyciski i wyświetlacz:
1. Stwórzmy nowy projekt Greenfoot’a nazywając go Kalkulator.
2. Stwórzmy nową klasę Kalkulator, która dziedziczy z klasy World. O klasie tej warto myśleć jako o szkielecie kalkulatora do którego następnie dodamy przyciski
a. Jako tło kalkulatora wybierzmy sandstone.jpg z menu backgrounds:

Jmk-kalkulator image14.png

3. Zakończmy tworzenie klasy Kalkulator klikając na przycisk Ok i skompilujmy projekt klikając na Compile.

Hierarchia przycisków numercznych

Kalkulator potrzebuje dziesięciu przycisków numerycznych reprezentujących cyfry arabskie. My wykorzystamy potęgę programowania obiektowego i najpierw zdefiniujemy klasę PrzyciskKalkulatora, która będzie wspólną nadklasą dla przycisków numerycznych i funkcyjnych. Gotowa hierarchia klas będzie wyglądała tak, jak na obrazku obok.

Jmk-kalkulator image09.png

Warto zwrócić uwagę na to, że stworzone klasy nie są wyświetlane pod klasą Actor. Związane jest to z tym, że klasy te nie dziedziczą bezpośrednio z klasy Actor tylko z klas związanych z kontrolkami.

Co to są kontrolki? Kontrolki to klasy wykorzystywane dla ułatwienia interakcji z użytkownikiem. Przykładem kontrolki może być klasa odpowiedzialna za przycisk wyświetlany na ekranie lub pole tekstowe służące do wprowadzanie tekstu. W typ wypadku kontrolkami będą klasy PrzyciskNumeryczny, PrzyciskFunkcyjny. Zapamiętaj, że kontrolki pozwalają kontrolować działanie programu!

Omówienie klasy PrzyciskKalkulatora. Oto kod klasy PrzyciskKalkulator:

Jmk-kalkulator image08.png

1. Na początku zwróćmy uwagę na to, że nasza klasa nie dziedziczy bezpośrednio z klasy Actor tylko z klasy Button (PrzyciskKalkulatora extends Button). Klasa Button jest właśnie klasą kontrolką reprezentującą przycisk. Poprzez wykorzystanie relacji sprawiamy, że klasa PrzyciskKalkulatora też jest przyciskiem i posiada funkcjonalności klasy Button.
a. Aby stworzyć klasę nie dziedziczącą z klasy Actor musimy wykorzystać opcję Edit => New Class …

Jmk-kalkulator image01.png

2. Po stworzeniu klasy pamiętajmy, aby dopisać do niej “extends Button” tak, jak przedstawiono na obrazku wyżej.
3. Następnie dopiszmy metodę konstruktora (konstruktor), który pozwoli stworzyć obiekty przycisków.
a. W linijce 6 mamy deklaracje konstruktora - konstruktor ten przyjmuje dwa parametry, pierwszym jest tekst wyświetlany na przycisku. Drugi to obiekt klasy Point, który będzie reprezentował rozmiar przycisku.
b. W linijce 7 mamy odwołanie do klasy konstruktora nadklasy (czyli klasy Button). Odwołanie takie jest konieczne i realizuje się je właśnie przez wykorzystanie słowa kluczowego super.
4. Gotowa klasa PrzyciskKalkulatora powinna wyglądać dokładnie tak, jak na obrazku. Jeśli Greenfoot dołączył nam jakieś inne metody lub zmienne usuńmy je - nie będą nam potrzebne!
5. Aha i oczywiście na koniec skompilujmy klasę.

Co to konstruktor? Konstruktor to specjalna metoda, która musi nazywać się tak samo jak klasa i nie deklarować zwracanego typu, używana do tworzenia obiektów np.: Samochod nazwaWlasna = new Samochod(); Pogrubiony tekst prezentuje wykorzystanie konstruktora.

Klasy PrzyciskNumeryczny oraz PrzyciskFunkcyjny:

Jmk-kalkulator image04.png
Jmk-kalkulator image05.png

Na tym etapie kod klas jest identyczny jak klasy PrzyciskKalkulatora. Po przepisaniu kodu pamiętajmy, aby skompilować kod i przejdźmy do kodu klasy Kalkulator.

Kod klasy Kalkulator:

Jmk-kalkulator image07.png

1. W linijkach 10-19 wykorzystujemy konstruktory, aby powtórzyć przyciski odpowiadające cyfrom.
a. Pierwszy argument konstruktora to tekst, który będzie wyświetlał się na przycisku.
b. Drugi argument jest to obiekt klasy Point definiujący rozmiar przycisku.
2. W linijkach 20-29 dodajemy stworzone wcześniej obiekt do świata, sprawiając tym samym, że będą one widoczne na ekranie.
a. Liczby będące argumentami metody addObject to współrzędne, pod którymi pojawi się obiekt na ekranie.
3. Skompilujmy projekt - na ekranie powinna pojawić się klawiatura kalkulatora.

Jmk-kalkulator image06.png

Teraz czas na dodanie przycisków funkcyjnych, zmodyfikujmy konstruktor klasy Kalkulator i dodajmy do niego poniższy kod:

Jmk-kalkulator image11.png

Kod jest analogiczny do kodu dodającego przyciski numeryczne. Po kompilacji uzyskamy:

Jmk-kalkulator image10.png

Wyświetlacz

W sekcji tej stworzymy klasę wyświetlacza i napiszemy niezbędne metody. Oto kod klasy wyświetlacz:

Jmk-kalkulator image00.png

1. Na początku zwrócimy uwagę, że klasa wyświetlacz rozszerza klasę TextBox. Klasa TextBox jest kontrolką służącą do wprowadzania lub wyświetlania tekstu. W naszym wypadku doskonale nada się jako wyświetlacz kalkulatora.
2. W linijce 6 mam deklaracje zmiennej typu liczba zmienno-przecinkowa (mówi nam o tym słowo double). Zmienną tą wykorzystamy do przechowywanie liczby wpisanej na wyświetlaczu.
3. W linijce 7 mamy deklaracje zmiennej typu tekstowego (String), będziemy przechowywać w niej znak działania.
4. Linijki 8-10 to deklaracja konstruktora. Nową klasą jest klasa Font, definiuje ona czcionkę wykorzystywaną w kontrolce.
5. Linijki 12-14 to znana nam już metoda act. Dzięki wykorzystaniu słowa super odwołujemy się do metody act z nadklasy. Zabieg ten jest potrzebny do prawidłowego działania kontrolki.
6. W metodzie pobierzLiczbe:
a. W linijce 17 pobieramy to, co jest wyświetlane w kontrolce. Dane wyświetlane w kontrolce mają postać tekstową, dlatego przypisujemy je do zmiennej typu String o nazwie liczba.
b. W linijce 18 zamieniamy tekst na liczbę zmienno-przecinkową i zwracamy (return).
7. Metody zapamietajLiczbe oraz zapamietajZnak ustawiają wartości dla zmiennych zadeklarowanych na początku klasy.
8. Metoda wyswietlLiczbe jako argument przyjmuje liczbę zmienno-przecinkową, następnie zamienia ją na tekst i ustawia do wyświetlenia na kontrolce.
9 .Metoda oblicz …. dokonuje obliczenia zależnie od wprowadzonego znaku i zapamiętanej liczby.
Na zakończenie tego rozdziału musimy dodać obiekt klasy Wyswietlacz do klasy kalkulator:

Jmk-kalkulator image02.png

1. W linijce 8 zadeklarowaliśmy zmienną wyswietlaczKalk typu Wyswietlacz. Zrobiliśmy to w klasie dlatego, że chcemy mieć dostęp do tej zmiennej z klas PrzyciskFunkcyjny i PrzyciskNumeryczny.
2. Linijki 12 i 13 powinny być już zrozumiałe.
3. Uwaga: instrukcja super (400, 600, 1) powinna pozostać pierwszą linijką w konstruktorze (wymaganie Javy).
Skompilujmy projekt - mamy gotowy wygląd kalkulatora!

TL;DR

1. Klasa Kalkulator:

import greenfoot.*;
import java.awt.Point;
import java.awt.Font;
 
public class Kalkulator extends World {
 
 
    Wyswietlacz wyswietlaczKalk;
 
    public Kalkulator() {     
        super(400, 600, 1);  
        wyswietlaczKalk = new Wyswietlacz(new Point(240, 20), "0.0", new Font("Helvetica", Font.PLAIN, 20));
        addObject(wyswietlaczKalk, 170, 230);   
 
        PrzyciskNumeryczny zero = new PrzyciskNumeryczny("0", new Point(60, 60));                        
        PrzyciskNumeryczny jeden = new PrzyciskNumeryczny("1", new Point(60, 60));                
        PrzyciskNumeryczny dwa = new PrzyciskNumeryczny("2", new Point(60, 60));
        PrzyciskNumeryczny trzy = new PrzyciskNumeryczny("3", new Point(60, 60));
        PrzyciskNumeryczny cztery = new PrzyciskNumeryczny("4", new Point(60, 60));
        PrzyciskNumeryczny piec = new PrzyciskNumeryczny("5", new Point(60, 60));
        PrzyciskNumeryczny szesc = new PrzyciskNumeryczny("6", new Point(60, 60));
        PrzyciskNumeryczny siedem = new PrzyciskNumeryczny("7", new Point(60, 60));
        PrzyciskNumeryczny osiem = new PrzyciskNumeryczny("8", new Point(60, 60));
        PrzyciskNumeryczny dziewiec = new PrzyciskNumeryczny("9", new Point(60, 60));                        
        addObject(zero, 80, 460);
        addObject(jeden, 80, 400);
        addObject(dwa, 140, 400);
        addObject(trzy, 200, 400);
        addObject(cztery, 80, 340);
        addObject(piec, 140, 340);    
        addObject(szesc, 200, 340);  
        addObject(siedem, 80, 280);
        addObject(osiem, 140, 280);    
        addObject(dziewiec, 200, 280);   
 
        PrzyciskFunkcyjny plus = new PrzyciskFunkcyjny("+", new Point(60, 60));
        PrzyciskFunkcyjny minus = new PrzyciskFunkcyjny("-", new Point(60, 60));
        PrzyciskFunkcyjny rownaSie = new PrzyciskFunkcyjny("=", new Point(60, 60));
        PrzyciskFunkcyjny czysc = new PrzyciskFunkcyjny("c", new Point(60, 60));        
        addObject(plus, 260, 340);
        addObject(minus, 260, 280);
        addObject(rownaSie, 260, 400);
        addObject(czysc, 140, 460);        
    }       
}

2. Klasa PrzyciskKalkulatora:

import greenfoot.*;
import java.awt.Point;
 
public class PrzyciskKalkulatora extends Button {
 
    public PrzyciskKalkulatora(String text, Point size) {
        super(text, size);
    }        
}

3. PrzyciskFunkcyjny:

import greenfoot.*;
import java.awt.Point;
 
public class PrzyciskFunkcyjny extends PrzyciskKalkulatora {
 
    public PrzyciskFunkcyjny(String text, Point size) {
        super(text, size);
    } 
 
}

4. PrzyciskNumeryczny:

import greenfoot.*;
import java.awt.Point;
 
public class PrzyciskNumeryczny extends PrzyciskKalkulatora {
 
    public PrzyciskNumeryczny(String text, Point size) {
        super(text, size);
    } 
 
}

5. Wyswietlacz:

import greenfoot.*;
import java.awt.Point;
import java.awt.Font;
 
public class Wyswietlacz extends TextBox {          
    double zapamietanaLiczba = 0.0;
    String zapamietanyZnak = "";    
    public Wyswietlacz(Point size, String text, Font font) {
        super(size, text, font);
    }
 
    public void act() {
       super.act();
    }   
 
    public double pobierzLiczbe() {
        String liczba = this.getText();
        return Double.parseDouble(liczba);
    }    
 
    public void zapamietajLiczbe(double liczbaDoZapamietania) {
        zapamietanaLiczba = liczbaDoZapamietania;
    }    
 
     public void zapamietajZnak(String znak) {
        zapamietanyZnak = znak;
    }    
 
    public void wyswietlLiczbe(double nowaLiczba) {
       this.setText(Double.toString(nowaLiczba));
    }      
 
    public void oblicz(double drugaLiczba) {
        if (zapamietanyZnak.equals("+")) {
            wyswietlLiczbe(zapamietanaLiczba + drugaLiczba);            
        } else if (zapamietanyZnak.equals("-")) {
            wyswietlLiczbe(zapamietanaLiczba - drugaLiczba);
        } 
    }
}

Poziom II: Realizacja obliczeń

Omówienie zadania:

W drugim etapie napiszemy algorytm, który sprawi, że kalkulator będzie wykonywał działania arytmetyczne:

  1. Logika klasy PrzyciskNumeryczny.
  2. Logika klasy PrzyciskFunkcyjny.

Realizacja zadania:

Zakodowanie PrzyciskuNumerycznego

Klasa PrzyciskNumeryczny będzie odpowiadała za odczytywanie liczb, które podał użytkownik kalkulatora. Do klasy PrzyciskNumeryczny dodajmy poniższe metody:

Jmk-kalkulator image13.png

Zacznijmy od omówienia metody act:

  1. Odwołanie do metody act z nadklasy w linijce 11 jest wymagane do poprawnego działania kontrolki.
  2. W linijce 12 za pomocą metody wasClicked sprawdzamy czy guzik numeryczny został kliknięty.
  3. Jeśli guzik został kliknięty to za pomocą kodu w linijce 13 pobieramy tekst - cyfrę klikniętego przycisku.
  4. W linijce 14 zamieniamy tekst z cyfrą na liczbę zmienno-przecinkową.
  5. W linijce 15 wywołujemy metodę wypiszNaWyswietlacz podając jako parametr klikniętą liczbę.

Omówienie metody wypiszNaWyswietlacz:

  1. W linijce 20 pobieramy nasz świat - czyli Kalkulator.
  2. Następnie pobieramy obiekt wyświetlacza z kalkulatora i przypisujemy do zmiennej blatWyswietlacz.
  3. W linijce 23 zamieniamy tekst z wyświetlacza na liczbę.
  4. W linijce 24 obliczamy wartość nowej liczby podanej przez użytkownika. Prześledźmy to na przykładzie:
    Użytkownik chce wpisać liczbę 13 na kalkulatorze.
    Najpierw klika 1.
    Następnie klika liczbę 3.
    Aby wyświetlić liczbę 13 mnożymy 1 razy 10 i dodajemy 3.
  5. W linijce 25 wyświetlamy nową liczbę na wyświetlaczu za pomocą metody zdefiniowanej w klasie Wyswietlacz.
  6. Skompilujmy i przetestujmy wpisywanie liczby:
Jmk-kalkulator image12.png

Zakodowanie PrzyciskuFunkcyjnego

Klasa PrzyciskFunkcyjny odpowiada za obsługę pozostałych przycisków. Dodajmy do niej poniższą metodę act:

Jmk-kalkulator image03.png
  1. Wywołanie w linijce 11 jest niezbędne do prawidłowego działania kontrolki.
  2. Jeśli któryś z przycisków funkcyjnych został kliknięty to za pomocą linijek 13-16 pobieramy znak klikniętego przycisku.
  3. Za pomocą instrukcji if w linijce 17 sprawdzamy czy został kliknięty plus lub minus. Znak || odpowiada logicznej alternatywie. Czyli do kodu w linijkach 18-21 przejdziemy wtedy, gdy użytkownik kliknął znak plus lub minus.
  4. W linijce 18 zapamiętujemy znak działania (wykorzystamy to potem w metodzie oblicz w wyświetlaczu).
  5. W linijce 19 pobieramy to, co jest wyświetlane na wyświetlaczu i zapisujemy tą wartość w linijce 20.
  6. Następnie w linijce 21 zerujemy zawartość wyświetlacza przygotowując go do wpisania kolejnej liczby.
  7. Jeśli został kliknięty znak równa się to obliczamy i wyświetlamy wynik działania na aktualnej i zapamiętanej liczbie (linijka 23).
  8. Jeśli został kliknięty klawisz c to czyścimy zapamiętane dane.

TL;DR

1. PrzyciskNumeryczny:

import greenfoot.*;
import java.awt.Point;
 
public class PrzyciskNumeryczny extends PrzyciskKalkulatora {
 
    public PrzyciskNumeryczny(String text, Point size) {
        super(text, size);
    } 
 
    public void act() {   
       super.act(); 
       if (wasClicked()) {           
            String tekstWcisnietaCyfra = this.getText();                        
            double wcisnietaCyfra = Double.parseDouble(tekstWcisnietaCyfra);
            wypiszNaWyswietlacz(wcisnietaCyfra);      
       }
    } 
 
    public void wypiszNaWyswietlacz(double wcisnietaCyfra){
        Kalkulator kalkulator = (Kalkulator) getWorld();
        Wyswietlacz blatWyswietlacz = kalkulator.wyswietlaczKalk;
        String tekstZWyswietlacza = blatWyswietlacz.getText();
        double staraLiczba = Double.parseDouble(tekstZWyswietlacza);
        double nowaLiczba = staraLiczba * 10 + wcisnietaCyfra;
        blatWyswietlacz.wyswietlLiczbe(nowaLiczba);                                      
    }     
 
}

2. PrzyciskFunkcyjny:

import greenfoot.*;
import java.awt.Point;
 
public class PrzyciskFunkcyjny extends PrzyciskKalkulatora {
 
    public PrzyciskFunkcyjny(String text, Point size) {
        super(text, size);
    } 
 
     public void act() {   
       super.act(); 
       if (wasClicked()) {
            Kalkulator kalkulator = (Kalkulator) getWorld();
            Wyswietlacz blatWyswietlacza = kalkulator.wyswietlaczKalk;
 
            String wcisnietaZnak = this.getText();
            if (wcisnietaZnak.equals("+") || wcisnietaZnak.equals("-") ) {
                blatWyswietlacza.zapamietajZnak(wcisnietaZnak);        
                double aktualnaLiczba = blatWyswietlacza.pobierzLiczbe();
                blatWyswietlacza.zapamietajLiczbe(aktualnaLiczba);
                blatWyswietlacza.wyswietlLiczbe(0.0);
            } else if (wcisnietaZnak.equals("=")) {
                blatWyswietlacza.oblicz(blatWyswietlacza.pobierzLiczbe());
            } else if (wcisnietaZnak.equals("c")) {
                blatWyswietlacza.wyswietlLiczbe(0.0);  
                blatWyswietlacza.zapamietajZnak(""); 
                blatWyswietlacza.zapamietajLiczbe(0.0);
            }          
       }
    }  
 
}

Jako zadanie domowe należy dodać mnożenie i dzielenie!