Dialogit ja ponnahdusikkunat

Tässä dokumentissa tarkastellaan ohjelmissa yleisesti käytettävien dialogien lisäämistä sekä kurssin FXGui-apupaketin käyttöä.

Tämä sivu ei ole vain "FYI", vaan tarvitset tämän neuvoja harjoitustyön tekemiseen.

Muista taas kommentoida rohkeasti dokumentin marginaaliin jos jokin on epäselvää tai ei onnistu (tai saat ahaa-elämyksiä). Palautteesi voi ratkaista muidenkin ongelmia :)

1. JavaFX:n valmiit dialogit

JavaFX:ssä on valmiina kysymys- ja varoitusdialogeja. Valmiit dialogit ovat yleensä pieniä modaalisia ponnahdusikkunoita. Modaalisuus tarkoittaa, että käyttäjä ei voi tehdä mitään muuta ennenkuin on kuitannut dialogin pois. Modaalisuuteen palataan myöhemmin tässä dokumentissa.

Löydät valmiita koodiesimerkkejä alempaa tästä dokumentista sekä code.makeryn sivuilta.

.java / .fxml Kannattaa heti opetella tunnistamaan, mikä koodi kuuluu .fxml-tiedostoon (ne missä koodi on xml-muodossa) ja mikä .java-tiedostoon. Kyseessä on kaksi aivan eri kieltä. Yleensä esimerkeissä oleva Java-koodi sijoitetaan Eclipsessä controller-luokkaan jonkin tapahtumakäsittelijä-metodin koodin yhteyteen.

Interaktiivisen esimerkin rajoitukset: Alla olevissa TIM-esimerkeissä koodi ajetaan yliopiston palvelimilla olevassa virtuaalikoneessa siihen asti kun dialogi on tullut näytölle, siten TIM ottaa dialogista kuvankaappauksen ja esittää sen sinulle. Tämän takia et voi painella dialogien painikkeita. Myös otsikkopalkit puuttuvat esimerkeistä, vaikka ne nimetäänkin koodissa.

Tämän sivun interaktiiviset osiot ovat kuitenkin mainioita harjoitusalustoja dialogien ulkoasujen harjoitteluun. Huomaa kuitenkin dialogien layoutin käyttöjärjestelmäsidonnaisuus: valmiita dialogeja käytettäessä OK- ja Cancel-painikkeiden järjestys vaihtuu sen mukaan mikä käyttöjärjestelmä on käytössä. Windowsissa OK-painike on Cancel-painikkeen vasemmalla puolella ja muissa OK-painike on oikeassa laidassa.

1.1 Alert (box)

Mikä? Alert boxilla tarkoitetaan pientä ponnahdusikkunaa, jonka avulla halutaan esimerkiksi varmistaa, että käyttäjä varmasti huomaa jonkin asian (ìnformation-tyyppi) tai esimerkiksi antaa selkeän hyväksynnän jatkamiselle (confirmation`-tyyppi).

Alert boxien käyttöä kannattaa harkita. Mitä enemmän niitä käyttää, sitä vähemmän käyttäjä kiinnittää niiden sisältöön huomiota.

Kokeile! Muokkaa ja aja alla olevaa koodia. Huomaa, että tulokset ovat .png-muotoisia kuvia, eli voit luoda kuvia myös tässä harjoitustyösi suunnitelmaa varten.

Jos jokin on epäselvää, heitä kysymyksiä TIMin kommenttityökalulla marginaaliin :)

Esimerkkikoodi: Simppeli ´information`-tyypin alert, joka kuitataan yhdellä painikkeella.

# AlertExample

Näyttää vain harmaita laatikoita. Haluaisin käytää tätä suunnitelman alertboxien kuviin, mutta nyt ei onnistu ja dedline on tänään. Ei ole hyvä tämä!

VL: kyllä mulla toimii. Onkohan sun koodi pielessä? Sitten näytä koko koodi niin näet valmiin ohjelman jonka voi copy/pasteta Eclipseen ja käyttää sieltä.

Lukekaa ja tehkää ehdottomasti tuo:

https://tim.jyu.fi/view/kurssit/tie/ohj2/tyokalut/JavaFX/kaytto

niin opitte käyttämään Eclipseä samalla. Mutta kokeilkaa tässäkin muutaman kerran, sillä toimintalogiikka on sellaien että ohjlma käynistetään ja odotetaan hetken ja sitten otetaan siitä kuva. Riippuen kuormasta tuo kuva voi olla valmis ennemmin tai myöhemmin.

01 Jun 17 (edited 24 Jan 18)

Mihin tämä vieressä oleva koodi pitäisi siis kopioida, että ponnahdusikkunan saisi scenebuilderin kautta näkymään?

VL: ei sitä mitenkään scenebuilderistä saa näkymään :-) Tuo on Javaa. Mutta johonkin semmoiseen handleXXX-metodiin, tosin helpommalla pääsee kun tekee kuten luennossa, että käyttää niitä yhden rivin versioita. Mutta ht2-suunnitelman kuvaksi sen voi ajaa tässä ja ottaa tästä ruutukaappauksen.

04 Feb 20 (edited 04 Feb 20)

Mikäli dialogin ulkoasuun haluaa vaikuttaa, voisi sen tehdä tyyleillä (kokeile laittaa edellä ennen alert.showAndWait() -kutsua):

        alert.getDialogPane().setStyle(" -fx-max-width:200px; -fx-max-height: 800px;"+
                                       " -fx-pref-width: 200px; -fx-pref-height: 800px;");

Tai sama voidaan tehdä myös käyttäen vastaavia metodeja:

        alert.getDialogPane().setMaxWidth(200);
        ...
        alert.getDialogPane().setPrefHeight(800);

Fontin voisi vaihtaa tasaväliseksi esim:

      alert.getDialogPane().setStyle("-fx-font-family: monospace;");

Esimerkkikoodi: Confirmation-tyypin alert box, joka pyytää käyttäjää tekemään Kyllä/Ei -valinnan:

# AlertExampleButtonsa

Vinkki! Käy nappaamassa koodia Code.makeryn esimerkeistä ja kokeile ajaa niitä TIMissä.

1.2 TextInputDialog

Käyttäjältä voidaan pyytää dialogi-ikkunassa myös muutakin, kuin painikkeiden klikkailua. Esimerkiksi tekstiä voit käyttäjältä kysyä seuraavalla tavalla:

            TextInputDialog dialog = new TextInputDialog("tähän tulee muodostajassa ollut teksti");
            dialog.setTitle("Tähän tulee Title");
            dialog.setHeaderText("Tähän tulee HeaderText");
            dialog.setContentText("Tähän tulee ContentText:");

# TextInputExample

Esimerkissä käyttäjän vastaus tulostetaan konsoliin System.out.println(answer.get()); -lauseella, mutta käyttäjän vastausta voi käyttää muuhunkin.

# FXGui

2. Dialogit FXGui.jarissa

Jos olet jo rakennellut harjoituskäyttöliittymää SceneBuilderissa, niin kurssia varten luotu FXGui-aliohjelmakirjasto on jo hieman tuttu.

Katsoin tuota FXGui -lähdekoodia ja siellä näytti olevan paljon enemmän erilaisia komponentteja, kuin mitä scenebuilderiini ilmestyi, kun sen sinne hain? (esimerkiksi dialogs.java ei ainakaan itselläni scenebuilderissa näy, mutta en tiedä, kuuluuko sen edes sinne tulla?)

VL: Joo, kaikki mitä siellä on ei ole komponentteja, osa on metodeja tai staattisia aliohjelmia joiden avulla luodaan sitten ajon aikana jotakin. Esim nuo dialogit ovat sellaisia että ne ilmestyvät kun ohjelmaa ajetaan, eli niitä eivät komponenttina laittaa toisen dialogin sisälle. Mutta tässä ohjeissa on miten ne saadaan koodina näkyviin ja niitähän voi käyttää tästä TIMistäkin ja vaihdella arvoja ja ottaa kuvakaappauksia HT:n suunnitelmaa varten.

24 Jan 21 (edited 24 Jan 21)

Ilouutinen on, että ´FXGui´ helpottaa sinua myös dialogien käytössä, kunhan vältät tyypillisen aloittelijan (ja kokeneemmankin) virheen ja muistat importata FXGui-kirjaston sekä lisätä sen projektin luokkapolkuun.

Eli kaikissa käyttötapauksissa lisää .java-tiedoston import-osaan aina:

import fi.jyu.mit.fxgui.*;

Alta löydät esimerkit edellä esiteltyjen alert boxien (information ja confirmation) sekä TextInputDialogin käytöstä FXGui-kirjaston avulla.

2.1 showMessageDialog

Esimerkki: Informoivan alert boxin luominen on näin helppoa:

# showMessageDialog

2.2 showQuestionDialog

Esimerkki: Confirmation-tyyppinen Kyllä/Ei -kysely onnistuu näin:

# showQuestionDialog

2.3 showInputDialog

Esimerkki: Käyttäjältä voi pyytää tekstiä (TextInputDialog) näin:

# showInputDialog
# callback

2.4 Dialogin ulkoasuun vaikuttaminen

Kaikkiin edellä mainittuihin kutsuihin voidaan lisätä viimeiseksi parametriksi takaisinkutsu, jolla saadaan dialogi käyttöön ennen sen näyttämistä. Näin voidaan esimerkiksi säätää näytettävän dialogin kaikkia asetuksia, esimerkiksi leveyttä (kokeile lisätä edellisiin):

	        Dialogs.showMessageDialog("Ei osata vielä lisätä",
	                dlg -> dlg.getDialogPane().setPrefWidth(400));

Mikäli halutaan tehdä useampia muutoksia, pitää nuolen jälkeinen lause tehdä aaltosuluilla kootuksi lauseeksi:

        Dialogs.showMessageDialog("Ei osata vielä lisätä",
           dlg -> {
             dlg.getDialogPane().setPrefWidth(200);
             dlg.getDialogPane().setPrefHeight(400);
           });

Luonnollisesti asetuksia voidaan säätää myös luvun alun esimerkin setStyle-metodilla.

        Dialogs.showMessageDialog("Ei osata vielä lisätä",
           dlg -> dlg.getDialogPane().setStyle(
             " -fx-max-width:200px; -fx-max-height: 400px;"+
             " -fx-pref-width: 200px; -fx-pref-height: 400px;"));

3. Ikkunan näyttäminen modaalisena

Usein ohjelmissa on useita näkymiä. Näitä voidaan hoitaa joko niin, että yhdessä "ikkunassa" vaihdetaan sisältöä. Tämä on varsin tyypillistä esimerkiksi mobiilisovelluksille.

Toinen vaihtoehto on avata uusia ikkunoita. Tämä taas on tyypillinen tapa työpöytäsovelluksissa. Tavalliselle peruskäyttäjälle useiden ikkunoiden käyttäminen on osoittautunut haastavaksi. Siksi eräs tapa uuden ikkunan avaamiseksi on avata se modaalisena, eli sellaisena että se estää muiden ikkunoiden käyttämisen kunnes avattu ikkunan on suljettu. Tämä periaatteessa tuo saman tilanteen kuin ikkunan sisällön vaihtaminen, paitsi että käyttäjälle jää selvä kuva siitä, mihin palataan kun ikkuna suljetaan.

Sen lisäksi että modaaliset ikkunat ovat selkeämpiä käyttäjälle, ne ovat myös hieman selkeämpiä ohjelmoijan näkökulmasta. Mikäli ikkuna suljetaan OK painikkeesta hyväksytään se mitä ikkunassa on tehty, muuten hylätään. Esimerkkejä modaalisista dialogeista oli edellä olevat valmiit Alert yms. dialogit.

Alempana näytetään miten tehdään modaaliseksi .fxml-tiedostossa esitetty sisältö.

3.1 Käyttö

Pyritään käytössä samaan kuin Alert-dialogien kanssa, että ikkunan käynnistäminen olisi pääohjelma puolesta mahdollisimman helppoa.

Alla on interaktiivinen TIM-esimerkki, jonka ajaminen vaatii että ensin tallennat ja käännät sen alapuolella olevat tiedostot.

Esimerkki Kutsutaan koodissa käyttäjän syötettä pyytävää käsittelijää.

# modalInputMain

Jotta yllä oleva koodi voidaan ajaa, paina alta "tallenna" (ja käy kääntämässä vielä seuraava tiedosto)

Esimerkki: Suunnitellaan dialogi KerhonNimiView.fxml-tiedostoon (huom. ei siis pääikkunan tiedosto) vaikkapa SceneBuilderillä tai ihan vaikka käsin Eclipsessa. Klikkaa "Näytä koko koodi", niin saat paremman käsityksen millaista koodia .fxml-tiedostoon syntyy:

# modalKerhonNimiView

The controller 'KunnanNimiController' has no field 'hakuehtoo' Ilmotus ei tuu problems ikkunaan vaan näkee vaan fxml tiedostoa selaamalla.

VL: Onko siellä kontrollerissa hakuehtoo-nimistä @FXML alkiosta attribuuttia? Koska nähtävästi tuon niminen on siellä .fxml-tiedostossa.

12 Feb 18 (edited 14 Feb 18)

Huomaa, että .fxml-tiedostossa on määritelty alla oleva .java-tiedoston luokka controlleriksi.

<BorderPane ... fx:controller="modalDialog.KerhonNimiController"> 

Paina allaolevasta "käännä" ja palaa ylemmäs kokeilemaan ohjelmaa.

Tässä tehdään kontrolleri, jossa on staattisena metodina tuon ikkunan käynnistäminen ja näyttäminen ja vastauksen hakeminen dialogista. Klikkaa "Näytä koko koodi", niin näet millainen aliohjelman pitäisi olla. Huomaa että tämä kontrolleri pitää olla mainittuna vastaavassa .fxml-tiedostossa

# KerhonNimiController
# shell

Onnistuuko? Jos jokin ei ole selvää, niin et varmasti ole ainoa - kysy tai ihmettele rohkeasti kommentoimalla sopivaa kohtaa marginaaliin :)

3.2 Modaalisen ikkunan sulkeminen

Modaalinen ikkuna voidaan sulkea esimerkiksi käyttämällä ModalController -luokasta löytyvää metodia closeStage(Node n). Se siis sulkee stagen (käytännössä ikkunan), johon tietty node (JavaFX:n komponentti) kuuluu.

Kyseinen metodi vaatii sen, että sille annetaan parametrina jokin fx:id:llä määritelty JavaFX:n komponentti, joka on määritelty controlleriluokkaa vastaavassa .fxml-tiedostossa.

Esimerkiksi, jos controllerluokasta (esim. KerhonNimiController.java) löytyy rivit

@FXML private void handleCancel() {
    ModalController.closeStage(textVastaus);
}

niin siellä on oltava määriteltynä myös jokin JavaFX:n komponentti, tässä tapauksessa TextField, jonka fx:id:ksi on asetettu textVastaus

@FXML private TextField textVastaus;

ja vastaavassa .fxml -tiedostossa (esim. KerhonNimiView.fxml) on määritelty jollekin TextField -komponentille fx:id:ksi

<TextField fx:id=”textVastaus” … ></TextField>
# FXGuiModal

4. Modaalinen dialogi FXGuin avulla

Edellä on paljon koodia, joka täytyy toistaa lähes samanlaisena dialogista riippumatta.

4.1 Dialogille oletuskontrolleri

FXGui.jar-kirjastossa tämä koodi on valmiina ja minimissään sitä voidaan käyttää tyyliin:

Tämä toimii, kun haluan avata uuden modaalisen ikkunan käyttöliittymääni. Onko mahdollista liittää "KerhonNimiView.fxml"-tiedostoon uutta, erillistä controller-tiedostoa? SceneBuilderista olen yrittänyt, ja ohjelma kaatuu, kun yrittää toteuttaa vasemmalla olevaa komentoa fxml-tiedostolle, joka on linkitetty erilliseen controlleriin.

E: Kuten ohjeessa lukeekin, piti vain toteuttaa rajapinta, eli "KerhoGUIController implements ModalControllerInterface".

06 Feb 18 (edited 08 Feb 18)

Implementointi antaa virheen "ModalControllerInterface is a raw type. References to generic type ModalControllerInterface should be parameterized", mitä se tarkoittaa? Ohjeissa on mukana "oletus", mutta en löydä selitystä sille. Onko kyseessä "oletus"-niminen muuttuja vai missaanko jotain muuta?



VL: sen on arvo jota käytetään oletuksena josta lähdetään liikkeelle. Ks alla oleva käyttöesimerkki.
KerhonNimiController.java

13 Feb 18 (edited 13 Feb 18)
  ModalController.showModal(KerhonNimiController.class.getResource("KerhonNimiView.fxml"),
                "Kerho", null, oletus);

Modaalisen dialogin aukaisu toimii Eclipsessä ajettuna, mutta jar-tiedostosta ajamalla tulee RuntimeException, "Caused by: java.lang.ClassNotFoundException: fi.jyu.mit.fxgui.ModalControllerInterface". Olen noita classpatheja tarkistellut, mutten keksinyt korjausta. Osaisiko joku neuvoa?

VL: Onko ihan varma että sulla on polussa se Java JDK joka itse tehtiin? Ja onko JARia tehtäessä pakattu mukaan ne omat kirjastot? Avaappa se ,jar jollakin 7Zip tai vastaavalla ohjelmalla ja katso löytyykö sieltä tuota classia.

08 Feb 22 (edited 08 Feb 22)

Em. toimii jos .fxml-tiedostossa on kontrolleriksi laitettu:

<BorderPane xmlns="... fx:controller="fi.jyu.mit.fxgui.ModalController">

Tällöin ei tietenkään saada mitään dialogikohtaista toimintaa. Mutta tuo kelpaa ensimmäiseksi vaihtoehdoksi itse suunnitellun dialogin näyttämiseksi.

Parametri oletus on kontrollerille menevä arvo, jolla kontrolleri tekee datan tyypistä riippuen jotakin, millä näyttää oletuksen arvot dialogissa ja mikäli käyttäjä ei muuta mitään, niin palautetaan oletus "sellaisenaan".

Esimerkiksi yhden merkkijonon kysymisessä oletus voi olla pohjaan näytettävän merkkijonon arvo. Kerhon jäsenen tapauksessa se voi olla Jasen, johon on täytetty attribuutit valmiiksi ja joiden arvot dialogi laittaa pohjaksi (kontrollerin tekijän pitää itse koodata tämä) vastaaviin syöttökenttiin.

Mitä tuo "oletus" siis konkreettisesti tekee ? Aiemmasta vastauksesta ei oikein pysty käsittämään. Laitoin arvoksi 21 ihan lonkalta, ja ainakin sain ikkunan avautumaan ;)

VL: Oletus on merkkijono joka näytetään siinä kysymysboxissa pohjana (oletuksena). Toki riippuu dialogin tallentamasta tyypistä, jossakin toisessa tapauksessa voi olla jotakin muuta. Esim aikanaan Jäsen-luokan olion kysymisessä Jasen-olio jota muokataan.

01 Feb 22 (edited 01 Feb 22)
Kontrollerin asettaminen SceneBuilderissa.
Kontrollerin asettaminen SceneBuilderissa.
# omakontrolleri

4.2 Dialogille oma kontrolleri

Mikäli halutaan dialogikohtaista toimintaa, pitää olla tehtynä kontrolleriluokka, joka on mainittu .fxml-tiedostossa ja kontrolleriluokan pitää toteuttaa rajapinta ModalControllerInterface, eli olla tyyliin:

public class KerhonNimiController implements ModalControllerInterface<String> {

Kontrolleriin on luvatun rajapinnan takia toteutettava metodit:

  • public void setDefault(TYPE oletus) {
    • asetetaan mahdollinen alustustieto dialogin sisälle. Tässä parametri oletus on sama mikä on showModal-kutsussa ja TYPE sama kuin edellä kirjoitettiin kulmasulkuihin.
  • public void handleShown() {
    • metodi jota kutsutaan kun dialogi on tullut näkyväksi. Tässä on tarkoitus esimerkiksi laittaa kursori (focus) haluttuun paikkaan valmiiksi. Myöhemmin esiteltävää lambda-lauseketta kutsutaan ennen tätä. Toteutus voi olla myös tyhjä, mitään erityistä ei tarvitse tehdä.
  • public TYPE getResult() {
    • showModal kutsuu tätä kun dialogi on piilotettu ja tulos pitää palauttaa.

Tehdään edellinen dialogi uudelleen FXGui.jar-kirjastoa käyttäen. Asennetun FXGui-paketin ansiosta se onnistuu pienemmällä koodimäärällä. Käytön tekee helpoksi se, että yksi metodi hoitaa selkeästi dialogin luomisen JA näyttämisen SEKÄ lopulta myös palauttaa dialogista saadun tuloksen.

Voidaan käyttää samaa dialogia kuin edellä KerhonNimiView.fxml:

# modalfxKerhonNimiView2

Huomaa että .fxml-tiedostossa on eri kontrollerin määritys (muista että paketin nimi ja luokan nimi riippuvat siitä mihin olet niitä laittanut)

fx:controller="fxKerho.KerhonNimiController"

Kontrolleriluokan toteuttamiseksi riittää toteutaa rajapinta
ModalControllerInterface<String>
jota valmis staattinen metodi ModalController.showModal voi käyttää hyväkseen. Näin kontrolleriluokkaan tarvitsee kirjoittaa vain se koodi, joka käyttää hyväkseen käyttöliittymää. Rajapinta on geneerinen, eli funktion paluuarvo voi olla mikä tahansa oliotyyppi.

# KerhonNimiController2

Pääohjelman puolelle tämä ei aiheuta muutoksia.

# modalInputMain2
# shell2

Funktio showModal palauttaa valitun tyyppisen olion, edellisessä esimerkissä siis String-tyyppisen. Mikäli tehdään esimerkiksi modaalinen dialogi joka käsittelee jäsenen tietoja, voisi kutsu olla muotoa:

Jasen muokattu = ModalController.showModal(
                JasenDialogController.class.getResource("JasenDialogView.fxml"),
                "Kerho",
                modalityStage, jasen);

Tällöin esimerkiksi palautetaan joko viite alkuperäiseen jäseneen (ellei kontrolleri tee siitä kopioita) tai null mikäli painetaan Cancel. Kontrolleriluokka saa täysin päättää käyttäytymisen.

4.3 Enemmän parametreja modal-dialogille

Mikäli kontrolleriluokalle pitäisi viedä enemmän parametreja kuin pelkkä yksi muokattava parametri, voidaan käyttää showModal-funktion yleisempää muotoa:

    public static Jasen kysyJasen(Stage modalityStage, Jasen oletus, Kerho kerho) {
        return ModalController.<Jasen, JasenDialogController>showModal(
                JasenDialogController.class.getResource("JasenDialogView.fxml"),
                "Kerho",
                modalityStage, oletus, ctrl -> ctrl.setKerho(kerho));
    }

missä viimeinen parametri on esimerkiksi lambda-lauseke, jolla kerrotaan mitä tehdään kun dialogi on luotu valmiiksi. Tässä esimerkissä kutsutaan kontrolleriluokan setKerho-metodia. Tällä tavalla voidaan kontrolleriin laittaa haluttu määrä ominaisuuksia ennen kuin dialogi näytetään.

Tässä tapauksessa geneerinen metodi ei voi kääntäjän toimesta tietää geneerisiä tyyppejä automaattisesti, joten käytettävät tyypit pitää sanoa itse showModal-funktiolle:

ModalController.<Jasen, JasenDialogController>showModal(

Kutsu voitaisiin kirjoittaa myös muotoon:

        return ModalController.showModal(
                JasenDialogController.class.getResource("JasenDialogView.fxml"),
                "Kerho",
                modalityStage, oletus, ctrl -> ((JasenDialogController)ctrl).setKerho(kerho));

mutta tämä on pakotetun tyyppinmuunnoksen takia huonompi vaihtoehto.

# ruksi

4.4 Ruksin toiminnan hallinta

Jos modaalisen dialogin oikean ylänurkan ruksin käytös halutaan niin, että siitä sulkeminen palauttaa null:in, niin silloin kannattaa tehdä niin, että vain handleOK-metodi muuttaa palautettavan attribuutin arvon ei-nulliksi kuten edellä olevassa fxKerho/KerhonNimiController.java-esimerkissä.

Jos toisaalta halutaan ruksista jokin muu arvo, mutta kuitenkin halutaan tarkistaa tiedon oikeellisuus, niin voidaan tehdä esimerkiksi niin, että setDefault-metodissa alustetaan käsittelijä ruksista sulkemiselle:

@Override
public void setDefault(String oletus) {
    textVastaus.setText(oletus);
    ModalController.getStage(textVastaus).setOnCloseRequest((event) -> {
        String teksti = textVastaus.getText();
        if ( teksti.equals("") { // ei saa olla tyhjä vastaus
            event.consume();
            return;
        }
        vastaus = teksti;
    });
}

Edellä siis ruksista sulkemista ei hyväksytä jos tekstikenttään ei ole kirjoitettu mitään. Silloin "kulutetaan" pois ruksin tapahtuma ja sulkemista ei tapahtu.

Mikäli ruksin toiminta halutaan kokonaan estää, niin voitaisiin laittaa vain:

@Override
public void setDefault(String oletus) {
    textVastaus.setText(oletus);
    ModalController.getStage(textVastaus).setOnCloseRequest(event -> event.consume() );
}

Staattisen getStage-metodin kutsussa saa olla mikä tahansa komponentti joka on lomakkeella olemassa. Sen ainoa tarkoitus on antaa yksi komponentti, josta voidaanlähteä kiipeämään ylöspäin etsimään lomakkeen stagea.

Jos haluat tarkemmin nähdä mitä tapahtuu, katso lähdekoodia:

Uudelleen määriteltyjen (@override) metodien kutsujärjestys:

  • initialize
  • setDefault
  • handleShown

5. Ei-modaalinen (modeless) dialogi FXGUI:in avulla

Ei-modaalinen (modeless) dialogi voidaan tehdä vastaavasti, silloin kutsu on muotoa:

    public static TulostusController tulosta(String tulostus) {
        TulostusController tulostusCtrl = 
          ModalController.showModeless(TulostusController.class.getResource("TulostusView.fxml"),
                "Tulostus", tulostus);
        return tulostusCtrl;
    }

Funktio showModeless palauttaa luomansa kontrolleriluokan ja sen kautta voidaan asettaa lisäominaisuuksia kontrolleriin.

Käyttäjälle modeless-dialogit ovat yleensä hankalampia, koska ne aukeavat olemassa olevan ikkunan rinnalle ja voivat helposti jäädä sen alle. Myös ohjelmoijalle ne ovat haastavampia, koska ei ole selkeää ajanhetkeä, milloin niihin syötetty tieto pitäisi käyttää. Parhaiten ne sopivat tarkoituksiin, joissa näytetään jotakin tiettyä tietoa ohjelmasta, mutta sitä ei voida niissä muokata.

Kokemuksia, vinkkejä, lisälukemista

Sana on vapaa, lisää omia vinkkejäsi alle tai kommentoiden.

These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.