Tietojenkäsittelytiede Harjoitustehtäviä
Graafisten käyttöliittymien toteutus 31.1.2001
x1. +-------------------------------------------------------+
| Tämä tehtävä on pakollinen. |
| |
| Ratkaisu on lähetettävä sähköpostina osoitteella |
| gkt01@cs.joensuu.fi viimeistään 30.1.2001 klo 8.00. |
| |
| ÄLÄ LÄHETÄ VASTAUSTA LIITETIEDOSTONA VAAN OSANA ITSE |
| KIRJEEN TEKSTIÄ !!! |
| |
| Tuo harjoitustilaisuuteen ohjelmalistaus ja valmiiksi |
| täyttämäsi x-tehtävän arviointilomake. |
+-------------------------------------------------------+
Laadi C++:lla (n)curses-kirjastoa käyttävä merkkipohjainen (siis
ei graafinen) ohjelma, joka antaa käyttäjän tehdä valintoja va-
lintaruutujen ja valintanappien ryhmistä ja lopuksi tulostaa
käyttäjän tekemät valinnat. Ohjelma on myös testattava.
Valintaryhmien toiminnat ovat seuraavat:
- Valintaruuturyhmä: Joukko vaihtoehtoja, joista kukin voi
olla valittu (X) tai ei (_). Käyttäjä
voi liikkua vaihtoehdosta toiseen
näppäimillä NuoliYlös ja NuoliAlas ja
vaihtaa valintatilaa näppäimellä En-
ter.
- Valintanappiryhmä: Joukko vaihtoehtoja, joista yksi on
valittu (@) ja muut eivät ole (O).
Käyttäjä voi liikkua vaihtoehdosta
toiseen näppäimillä NuoliVasemmalle
ja NuoliOikealle (vaikka vaihtoehdot
ovatkin päällekkäin !) ja vaihtaa ny-
kyisen vaihtoehdon valituksi näppäi-
mellä Enter.
Valintaryhmiä voi olla näytöllä mielivaltainen määrä ja käyttäjä
pääsee ryhmästä seuraavaan näppäimellä Tab. Lisäksi numeroilla
1..9 pääsee suoraan ko. ryhmään (ja "suurinumeroisiin" ei tällä
tavalla pääse). Ryhmät voivat sijaita näytöllä osittain päällek-
käin ja ohjelman velvollisuus on "nostaa" kulloinkin käsiteltävä
ryhmä näkyviin. Käyttäjä voi käydä kussakin ryhmässä niin monta
kertaa kuin hän haluaa. Näppäimellä 'q' toiminta loppuu ja ohjel-
ma tulostaa voimassaolevat valinnat.
Näytölle tulevat valintaryhmät kuvataan tiedostossa, jossa on ku-
takin ryhmää kohden:
- rivi, jossa on ryhmän laji (r: ruutu, n: nappi) ja sen sijain-
tipaikan vasemman yläkulman rivi ja sarake
- kutakin vaihtoehtoa varten rivi, jossa on vaihtoehdon teksti
- rivi, jolla on merkki '#'
Tämä ohjaustiedosto voisi olla esimerkiksi seuraavanlainen:
r 5 20
Musta
Valkoinen
Punainen
Vaaleanvihreä
#
r 15 1
Aamiainen
Lounas
Päivällinen
Iltapala
Kahvit (2 kpl)
#
n 13 7
Puuvilla
Pellava
Villa
Keinokuitu
#
r 15 50
Maljakko
Vati
#
n 10 40
Kukka
Vilja tms.
#
Edellisen ohjaustiedoston tapauksessa näyttö voisi olla käyttäjän
tehtyä joitakin valintoja seuraavanlainen (reunoja leikattu pois):
===================================================================
_ Musta
X Valkoinen
X Punainen
_ Vaaleanvihreä
@ Kukka
O Vilja tms.
O Puuvilla
@ Pellava
_ Aam O Villa _ Maljakko
X Lou O Keinokuitu _ Vati
_ Päivällinen
X Iltapala
X Kahvit (2 kpl)
===================================================================
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
Valintaryhmät on toteuttava olioina käyttäen seuraavaa liittymän
määrittelyä:
#define maxTeksti 80
#define MaxValintoja 10
/* ------------- Yläluokka valintaryhmille ------------- */
class ValintaRyhma {
protected:
/* ... */
public:
/* Valintaryhmä muodostetaan antamalla muodostajalle parametreina
valintaryhmän vasemman yläkulman koordinaatit ja kutsumalla ope-
raatioita valinta kerran kutakin kyseiseen ryhmään kuuluvaa va-
lintaa kohti. (Muodostajana käytetään tietenkin aliryhmän
muodostajaa.)
Esim: ryhma = new RuutuRyhma(5,15);
virhe=ryhma->valinta("Vaihtoehto 1");
virhe=ryhma->valinta("Vaihtoehto 2");
virhe=ryhma->valinta("Vaihtoehto 3");
*/
ValintaRyhma(int rivi, int sarake);
virtual int valinta(char *teksti); // -1 jos virhe
/* Valintaryhmää käytetään seuraavilla operaatioilla:
piirry: Valintaryhmä tulostaa itsensä ruudulle ny-
kyisillä valinnoilla.
tuloRyhmään: Kursori on tulossa ryhmään. Operaatio si-
joittaa kursorin ensimmäisen vaihtoehdon
kohdalle.
nappaily: Käyttäjä on painanut jotain näppäintä, jon-
ka menetelmä saa parametrinaan. Operaation
on muutettava valintojen ulkoasu vastaavas-
ti ja sijoitettava kursori oikeaan kohtaan.
Esim: ryhma->piirry();
ryhma->tuloRyhmaan();
ryhma->nappaily(ALAS);
ryhma->nappaily(ALAS);
ryhma->nappaily(ENTER);
ryhma->nappaily(YLOS);
ryhma->nappaily('x');
ryhma->nappaily(ENTER);
ryhma->piirry();
ryhma->tuloRyhmaan();
*/
virtual void piirry();
virtual void tuloRyhmaan();
virtual void nappaily(char c);
/* Ryhmän voimassaolevia valintoja voi pyytää operaatioilla
ensValittu ja seurValittu, jotka palauttavat parametrissaan
osoittimen vaihtoehdon tekstiin ja omana arvonaan vaihtoehdon
numeron tai -1 jos valintoja ei enää ole.
Esim: ekaValinta = ryhma->ensValittu(valinnanTeksti1);
if (ekaValinta >= 0)
tokaValinta = ryhma->seurValittu(valinnanTeksti2);
*/
virtual int ensValittu(char *teksti);
virtual int seurValittu(char *teksti);
};
/* ------------- Valintaruutujen ryhmä ----------------- */
class RuutuRyhma : public ValintaRyhma {
/* ... */
};
/* ------------- Valintanappien ryhmä ------------------ */
class NappiRyhma : public ValintaRyhma {
/* ... */
};
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
Curses-kirjastosta tarvitaan tässä tehtävässä vain hyvin pientä
osaa. Seuraava esimerkki havainnollistaa kirjaston käyttöä:
/* curses-esimerkki (ohjelma.cc)
Ohjelman kääntäminen:
gcc -o ohjelma ohjelma.cc -lcurses
tai (ympäristöstä riippuen)
gcc -o ohjelma ohjelma.cc -lcurses -ltermcap
*/
#include <curses.h> // curses-kirjasto
#define ENTER 10
main ()
{ char c;
initscr(); cbreak(); noecho(); // Alusta curses
mvprintw(5,20,"Paina jotain: ");
refresh(); // Näytön päivitys
if ((c=getch()) == ENTER) {
move(10,0); printw("Painettu ENTER");
refresh();
} else {
mvprintw(10,0,"Painettu %c",c);
refresh();
}
c=getch(); // Jotta kerkiäisi näkemään tulostuksen
move(LINES-1,0); refresh(); endwin(); // Lopeta curses
}