Lisätietoa: Lukujen syöttäminen

Lukujen syöttäminen näppäimistöltä

Huomio: Jotta voit testata tämän luvun esimerkkejä, niin sinulla pitää olla käytössä PC. Nämä esimerkit eivät toimi iPadilla. iPadilla tiedot syötetään kosketusnäytön avulla.


Kuinka voitaisiin tehdä ohjelma, joka ensin kysyisi luvut. Lukujen syöttämisen jälkeen ohjelma laskisi ne yhteen ja tulostaisi vastauksen. Processing-ohjelmassa on komento: key, joka lukee näppäimen painallukset. Kokeile laittaa key-komento suoraan tekstintulostuskomentoon. Mitä huomaat?

// Ohjelman tehnyt: e-Oppi Oy
// 31.1.2017
void setup() {
size(600,400); // Määritellään ikkunan koko
textSize(30); // Tekstin koko 30 px
}
void draw() {
background(0); // Tyhjennetään tausta
text(key,100,50); // Tulostetaan näppäimen painallus
}


Kuten huomaat voit syöttää yksittäisiä merkin painalluksia tietokoneelle. Kuinka voitaisiin syöttää pidempiä lauseita. Tutkitaan seuraavaa esimerkkiä.

// Ohjelman tehnyt: e-Oppi Oy
// 29.1.2017
String teksti=""; // Teksti-muuttuja on alussa tyhjä.
void setup() {
size(600,400); // Määritellään ikkunan koko
textSize(30); // Tekstin koko 30 px
}
void draw() {
background(0);
text(teksti,100,50);
}
void keyPressed() {
teksti+=key; // Merkki lisätään teksti-muuttujaan
}


Processing-ohjelmassa löytyy void keyPressed () -lohko. Tämä lohko suoritetaan aina kun painetaan jotain näppäintä. Kun tähän lohkoon laitetaan komento: teksti+=key, niin tällöin saadaan yksittäiset merkkien painallukset lisättyä teksti-nimiseen muuttujaan, jossa muuttuja on määritelty String-tyyppiseksi. Aja ohjelma: kokeile kirjoittaa sanoja, lauseita ja paina myös Enter-painiketta.

Voimme tästä rakentaa ohjelman, joka summaa kaksi lukua yhteen. Se on seuraavanlainen.

// Ohjelman tehnyt: e-Oppi Oy
// 29.1.2017
String teksti=""; // Luku1:n teksti
String teksti2 =""; // Luku2:n teksti
int laskuri = 0; // Kuinka monta lukua syötetty
int luku1 = 0; // Ensimmäinen luku
int luku2 = 0; // Toinen luku
void setup() {
size(600,400); // Ikkunan koko
textSize(30); // Tekstin koko
}
void draw() {
background(0); // Tyhjennä tausta
text("Anna "+(laskuri+1)+". luku:"+teksti,100,50); // Kysy luku
text("Ensimmäinen luku "+luku1,100,100); // Näytä 1. luvun arv0
text("Toinen luku "+luku2,100,150); // Näytä 2. luvun arvo
text("Lukujen summa "+(luku1+luku2),100,200); // Näytä lukujen summa
if (laskuri > 2) { // Kun kolmas luku on syötetty
text("Et voi syöttää enempää lukuja",100,250);
}
}
void keyPressed() {
teksti+=key; // Lisää merkki merkkijonoon.
if (key =='\n') { // Jos painetaan Enter eli teksti-muuttuja sisältää Enterin
laskuri = laskuri + 1; // Kasvata luku laskuria
if (laskuri == 1) { // Jos ensimmäinen luku
luku1 = int(teksti2); // Sijoita luku1-muuttujalle kokonaisluku
}
if (laskuri == 2) { // Jos toinen luku
luku2 = int(teksti2); // Sijoita luku2-muuttujalle kokonaisluku
}
teksti=""; // Nollaa teksti-muuttuja
}
teksti2+=key; // Lisää viimeinen merkki (eli Enter) toiseen merkkijonoon
if (key =='\n') { // Jos painetaan Enter
teksti2=""; // Nollataan teksti2-muuttuja
}
}


Tässä ohjelmassa käytetään laskuria ja if-lausetta. If-lause esitellään seuraavassa kappaleessa ja laskuri kappaleessa 6. Ohjelman idea on se, että jokainen yksittäinen merkki lisätään teksti-muuttujaan. Kun vastaan tulee Enterin painallus, joka tässä on sama kuin: ’\n’, silloin kasvatetaan laskuria ja nollataan teksti-muuttuja. Ensimmäinen Enterin painallus määrää ensimmäinen luvun (laskuri =1) ja toinen Enterin painallus määrää toisen luvun (laskuri = 2). Ongelma on vain siinä, että teksti-muuttuja sisältää myös Enterin painalluksen. Tekstiä ei tällöin voi muuttaa kokonaisluvuksi. Tarvitsemme siis toisen teksti-muuttujan, nimeltään teksti2, jossa ei mukana ole Enterin painallusta. Teksti2-muuttujasta puuttuu siis viimeinen syötetty merkki. Lopussa tietysti lisäämme viimeisen merkin myös teksti2-muuttujaan ja nollaamme myös sen, jos viimeinen merkki on Enterin painallus.

Oheinen kuvasarja havainnollistaa ohjelmaa.

  1. Syötä ensin luku, esimerkiksi 12 ja paina lopuksi Enter.
  2. Nyt luku1-muuttuja saa arvon 12 ja lukujen summa on 12+0 = 12. Anna nyt toinen luku, esimerkiksi 34 ja paina lopuksi Enter.
  3. Nyt luku2-muuttuja saa arvon 34 ja lukujen summa on 12+34 = 46. Voit kokeilla syöttää vielä kolmannen luvun, esimerkiksi 76 ja lopuksi paina Enter.
  4. Koska nyt laskuri on suurempi kuin 2, niin tulostuu kommentti: ”Et voi syöttää enempää lukuja”.

Tekstikenttä

Kuten edellinen esimerkki osoittaa Processing-ohjelmassa lukuja voidaan lukea tekstisyötteestä key-komennolla, mutta tiedonsyötön rakenne poikkeaa perinteisestä tekstipohjaisten ohjelmointiympäristöjen lukujen syöttämiskomennosta, koska konsoli-ikkunassa rivi rullaa aina rivin alaspäin. Tässä tulostus ja tiedon syöttö tapahtuu koordinaatistoon sidotusti. Lukujen syöttämiseen on myös toinen ja ehkäpä fiksumpi lähestymistapa. Koska Processing-ohjelma toimii Java-alustalla, niin yksi tavallinen tiedonsyöttötapa tässä ympäristössä on tekstikenttien käyttäminen. Ongelma on vain siinä, että Processing-ohjelmointikielestä puuttuvat komennot tekstikenttien ja painonappien luomiseen. Tähän onneksi löytyy helppo ratkaisu, nimittäin ladattavat kirjastot. Tekstikentät ja painonapit on määritelty ControlP5 kirjastossa.

Mene kohtaan Add Mode…



Mene välilehdelle Libraries ja etsi sieltä kohta ControlP5. Tämä kirjasto sisältää tarvittavat komennot, jotta ohjelmaan voidaan lisätä tekstikenttiä ja painonappeja tiedon syöttämistä varten. Valitse ControlP5-kirjasto ja paina install-painiketta. Lopuksi tulee kommentti installed, ja kirjasto on asennettu.




Huomio: Tätä kirjastoa ei voi käyttää iPAD:lla tai Android tabletilla.


Tehdään seuraava ohjelma.

// Ohjelman tehnyt: e-Oppi Oy
// 29.1.2017
import controlP5.*; // Otetaan controlP5 kirjasto käyttöön
int luku1 = 0; // Määritellään muuttujat ja annetaan
int luku2 = 0; // niille alkuarvot nolla.
ControlP5 cp5; // Kuuntelijan määrittely
void setup() {
size(500,500); // Ikkunan koko
cp5 = new ControlP5(this); // Lisätään kuuntelija

PFont font = createFont("Arial",20);
// Määritetään fontti ja fonttikoko tekstikentälle

cp5.addTextfield("Luku1") // Lisätään tekstikenttä: Luku1
.setPosition(20,100) // Tekstikentän paikka
.setFont(font)
.setFocus(true)
;

cp5.addTextfield("Luku2") // Lisätään toinen tekstikenttä
.setPosition(250,100) // Tekstikentän paikka
.setFont(font)
.setFocus(true)
;

cp5.addBang("Laske") // Lisätään painonappi
.setPosition(20,180) // Painonapin paikka
.setSize(80,40) // Painonapin koko
.getCaptionLabel().align(ControlP5.CENTER,ControlP5.CENTER)
;
}
void draw() {
background(0);
textSize(20);
text("Lukujen summa on "+(luku1+luku2),20,300);
}
// Seuraava ohjelma ajetaan, kun painetaan Laske-painonappia
public void Laske() {
String vastaus1 = cp5.get(Textfield.class,"Luku1").getText();
//Komento lukee tiedon ensimmäisestä tekstikentästä
String vastaus2 = cp5.get(Textfield.class,"Luku2").getText();
// Komento lukee tiedon toisesta tekstikentästä
luku1 = int(vastaus1);
// Muutetaan vastaus1 kokonaisluvuksi ja sijoitetaan luku1 muuttujaan.
luku2 = int(vastaus2);
// Muutetaan vastaus2 kokonaisluvuksi ja sijoitetaan luku2 muuttujaan.
}


Jolloin saamme luotua ohjelman, jossa on kaksi tekstikenttää nimeltään: Luku1 ja Luku2. Lisäksi lisäämme painonapin nimeltään: Laske. Tekstikentät ja painonappi määritellään void setup () -lohkossa, joka suoritetaan vain kerran. Nyt voit syöttää luvut tekstikenttiin ja vasta lopuksi painetaan Laske-painonappia, tällöin tekstikenttien sisältö siirretään: luku1 ja luku2 muuttujiin lohkossa public void Laske (). Tämä lohko suoritetaan vain silloin kun painonappia painetaan. Kun muuttujilla laske1 ja laske2 on arvot, niin ne on helppo laskea yhteen ja tulostaa void draw () -lohkossa, joka siis pyörii ikuisessa silmukassa. Mielestäni tekstikenttien ja painonapin käyttäminen on paljon fiksumpaa kuin key-komennon käyttäminen. Key-komento sopii paremmin grafiikkakomponenttien ohjaamiseen ruudulla kuin tiedon syöttämiseen. iPadille sopii taas paremmin hiirikomennot. Palataan tähän uudestaan seuraavassa kappaleessa.

Ohjelman suoritus näyttää tältä, kun painonappia on painettu.


Syöttökenttä Javan avulla Processing-ohjelmaan

Processing-ohjelmassa ei ole syöttökenttää tekstille. Koska Processing-ohjelman taustalla pyörii Java-kääntäjä, niin voit ottaa käyttöön Javan syöttökentän komennolla: String muuttuja = showInputDialog("Tekstiä"); Tämä komento löytyy Javan kirjastosta: javax.swing.JOptionPane.*. Jotta voit käyttää tätä komentoa Processing-ohjelmassa, niin lisää kirjaston kutsukomento: import static javax.swing.JOptionPane.*; heti ohjelman alkuun.

Tehdään edellinen esimerkki uudestaan käyttäen Javan tekstisyöttökenttää. 

// Ohjelman tehnyt e-Oppi Oy
// 1.1.2018
import static javax.swing.JOptionPane.*;

void setup () {
size(400,400); // ikkunan koko
fill(0); // Tekstinväri musta
background(255); // Taustaväri valkoinen
textSize(20); // Tekstin koko 20
noLoop(); // void draw ()-lohko suoritetaan vain kerran
}
void draw () {
String vastaus1 = showInputDialog("Anna luku 1"); // Kysy ensimmäinen luku
String vastaus2 = showInputDialog("Anna luku 2"); // Kysy toinen luku
int luku1= int(vastaus1); // Konversio merkkijonosta kokonaisluvuksi
int luku2 = int(vastaus2); // Konversio merkkijonosta kokonaisluvuksi
text(luku1+" + "+luku2+" = "+(luku1+luku2),20,100); // Tulosta vastaus
}


Myös tässä on käytettävä konversiota: int(vastaus1) ja int(vastaus2), jotta saat muutettua syötettä vastaavan merkin kokonaisluvuksi. Kun ajat ohjelman, syöttökenttä näyttää tältä.


Ohjelma toimii muuten oikein, paitsi jos painaa Cancel-painiketta, tällöin ohjelma kaatuu. Ongelma tulee siinä, kun yritämme konversiolla muuttaa null-arvoa kokonaisluvuksi. Kun teemme seuraavan lisäyksen koodiin, niin ohjelma toimii myös silloin kun painetaan Cancel-painiketta. Ohjelma tulkitsee luvun silloin nollaksi.

// Ohjelman tehnyt e-Oppi Oy
// 1.1.2018
import static javax.swing.JOptionPane.*;

void setup () {
size(400,400); // ikkunan koko
fill(0); // Tekstinväri musta
background(255); // Taustaväri valkoinen
textSize(20); // Tekstin koko 20
noLoop(); // void draw ()-lohko suoritetaan vain kerran
}
void draw () {
String vastaus1 = showInputDialog("Anna luku 1"); // Kysy ensimmäinen luku
String vastaus2 = showInputDialog("Anna luku 2"); // Kysy toinen luku
int luku1 = 0;
int luku2 = 0;
if (vastaus1 != null) { // Jos vastaus1 ei ole Cancel (= null), niin tee
luku1= int(vastaus1); // konversio merkkijonosta kokonaisluvuksi
}
if (vastaus2 != null) { // Jos vastaus2 ei ole Cancel (=null), niin tee
luku2 = int(vastaus2); // konversio merkijonosta kokonaisluvuksi
}
text(luku1+" + "+luku2+" = "+(luku1+luku2),20,100); // Tulosta vastaus
}


If-lauseeseen tutustumme seuraavassa kappaleessa.