Tapahtumapohjainen ohjelmointi Juha-Matti Vanhatupa (vanhan kurssin Graafisen käyttöliittymän ohjelmointi materiaalia)
Erot perinteisiin sovelluksiin Sovelluksen kulku ei ole ennalta tiedossa. Start A B C D End Dispatcher A C B D End
Perinteinen sovellus void main(string[] args ) { string nimi, hetu, osoite; Console.WriteLine("Anna nimi: "); nimi = Console.ReadLine(); Console.WriteLine("Anna henkilötunnus: "); hetu = Console.ReadLine(); Console.WriteLine("Anna osoite: "); osoite = Console.ReadLine(); } Save(nimi, hetu, osoite);
Tapahtumapohjainen sovellus string nimi, osoite, hetu; static void main() { Application.Run( new Form1() ); } private void nimi_handler(string text){ nimi = text; } private void hetu_handler(string text){ hetu = text; } private void osoite_handler(string text){ osoite = text; } private void tallenna_click(){ Save(nimi, hetu, osoite); Close(); }
Ohjelmoijalle Ohjelman suoritus ei etene alusta loppuun Testaaminen vaikeutuu Kaikkia ohjelman toimintoja ei välttämättä edes koskaan käytetä
Tapahtumia synnyttävät Käyttäjän toimet, hiiren- ja näppäimistön painallukset Ajastimet Käyttöjärjestelmä (Sovellus itse)
Tapahtuman kulku Event generator Event Dispatcher Handler1 Handler2 Handler n
Tapahtuma Tapahtumille ei yleensä määritellä paluuarvoa Windowsissa yleinen tapa on merkitä tapahtuman kuuntelija onetuliitteellä Kuuntelijat tietynlaisia funktioita, jotka rekisteröidään kuuntelemaan tapahtumaa Esim. (Qt4): QPushButton* btnok = new QPushButton(this); connect(btnok, SIGNAL(clicked()), this, SLOT(OnOKCLicked()); void OnOKClicked() { // }
Tapahtumakuuntelijan toteutus QT signaalien ja slottien avulla.net eventtien avulla Java rajapintojen avulla GTK signaalien avulla WinApi sanomien avulla MFC makrojen avulla
Qt esimerkki Tapahtumakuuntelija luodaan kytkemällä olion lähettämä signaali (esim. nappulan clicked signaali) slot-funktioon. Kytkettyjen olioiden ei tarvitse tuntea toisiaan. Signaali lähetetään kun tietty tapahtuma tapahtuu (esim. nappulaa painetaan) ja tällöin kytkettyä slotfunktiota kutsutaan. Luokkien tulee periytyä QObject luokasta (joko suoraan tai periytyen jostain QObjectin aliluokasta) Luokkien esittelyssä tulee olla Q_OBJECT makro
Qt esimerkki class MainWindow : public QMainWindow { Q_OBJECT public: public slots: void helloworld(); };
Qt esimerkki MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { } ui->setupui(this); connect(ui->pushbutton, SIGNAL(clicked()), this, SLOT(helloWorld())); void MainWindow::helloWorld() { } ui->label->settext("hello World!");
Pääikkuna (top-level window) Jokaisella sovelluksella on pääikkuna (main window), joka luodaan ohjelman käynnistyessä. Esim. Qt:ssä mainfunktiossa. Pääikkuna sisältää yleensä otsikon, valikon, reunukset sekä minimize- ja maximize-painikkeet Kun pääikkuna suljetaan, myös sovelluksen suoritus päättyy Pääikkunalla ei ole parent-ikkunaa
Pääikkuna (top-level window)
Lapsikkuna (child window) Lapsi-ikkunalla (child window) on aina yksi isäntäikkuna (parent window) Paikkakoordinaatit suhteessa isäntäikkunaan Lapsi-ikkuna ei voi sijaita isäntäikkunan ulkopuolella
Dialogit Modaalinen vs modaaliton ikkuna Omistus-suhde (owner) Tarkoitettu lyhytaikaiseen kommunikaatioon käyttäjän kanssa Tyypillisesti ei menua, eikä minimize, mazimize painikkeita.
Z-järjestys
Ikkunan fokus Valittuna oleva ikkuna (kuvassa btn1) Komponentti, joka ottaa vastaan näppäinpainallukset jne. Käyttäjä voi vaihtaa focusta esim hiiren tai näppäimistön avulla
Tab-järjestys Tabulaattori-näppäimellä voidaan vaihtaa focus seuraavalle (lapsi)ikkunalle Suunnittele käyttöliittymä aina siten että sitä voidaan käyttää pelkän näppäimistönkin avulla! Tab