Tässä dokumentissa käydään läpi miten teet SceneBuilderilla Java-sovellukseesi graafisen käyttöliittymän. Opit, mm.:
.jar-tiedostossa.Tähän osioon liittyviä lukuja kurssimonisteessa:
Tämä dokumentti sisältää ohjeita sekä tekstimuodossa että suunnilleen samansisältöisinä videoina. Ohjevideoilla käytetään seuraavia pikanäppäimiä:
| Windows | OS X | Toiminto |
|---|---|---|
Ctrl-S |
Cmd-S |
tallenna |
F11 |
Cmd-F11 |
Eclipsessä ajaa ohjelman (debug) |
Ctrl-P |
Cmd-P |
SceneBuilderissä “ajaa” suunnitellun ikkunan |
Alt-Tab |
Cmd-Tab |
vaihdetaan Eclipsen, SceneBuilderin ja selaimen välillä |
Please
Miksi tämä on tässä eikä tuolla loppupuolella?
- VL: joo, huonostihan tähän on vastattu. Mutta kun tehtävä voi tehdä vähän kerrallaan ja kaikki eivät koskaan mene loppuun saakka, mutta tämän alun ohi kaikkien pitäisi kulkea. Suo siellä, vetelä täällä...
Mitä tuo Velps tarkoittaa?
Velp View-tilassa lisätä merkintöjä (kunhan ensi luo Velppejä). Oikeastaan tuon ei kuuluisi näkyä muuta kuin jo Velppejä on annettu tai olla Velp View-tilassa. Kukaan ei ole vaan muistanut sitä näkyvyysehtoa siihen kirjoittaa.SceneBuilder on graafinen työkalu, jonka avulla on helppo luoda ulkoasu ja graafinen käyttöliittymä (GUI) ohjelmaasi. SceneBuilder näyttää käytössä suunnilleen tältä:
Periaatteessa SceneBuilderilla voidaan rakennella graafisia käyttöliittymiä täysin ilman Eclipsen (tai vastaavan IDE:n) apua, mutta kun nyt kurssilla on tavoitteena tehdä sekä ohjelma, että sille käyttöliittymä on vain järkevää koordinoida käyttöliittymän ja ohjelman kehitystä yhdestä paikasta, tällä kurssilla siis Eclipsestä.
Periaatteessa JavaFX-ohjelman ulkoasu voitaisiin tehdä myös täysin ohjelmallisesti ilman SceneBuilderin kaltaista graafista työkalua, mutta ymmärrettävästi ulkoasun suunnittelu visuaalisesti on usein aluksi helpompaa.
Usein käytännössä graafista käyttöliittymää kehitetäänkin yhdistelemällä visuaalista ja ohjelmoinnillista työskentelyä. Esimerkiksi perussuunnittelu tehdään visuaalisella työkalulla ja sitten selkeästi toistuvia komponentteja lisätään ajonaikaisesti ohjelmakoodilla.
SceneBuilderilla luotujen ulkoasujen kuvauskielenä on FXML -formaatti, joka pohjautuu XML:ään. Tarkentimella .fxml olevia tiedostoja voidaan avata ja kirjoittaa myös millä tahansa tekstieditorilla, kuten NotePad++:lla tai Eclipsessä, ja niiden rakenne on aika ymmärrettävä. Eli pohjimmiltaan SceneBuilder on vain yksi vaihtoehto tietyn muotoisen xml-tiedoston muokkaamiseen.
Oraclen omat SceneBuilder-ohjeet löydät täältä, mutta pääset helpommin alkun tätä dokumenttia lukemalla ja upotettuja videoita katsomalla.
Aletaanpas tutustumaan tarkemmin itse käyttöön, mutta ennen kuin jatkat, niin varmista, että seuraavat on tehtynä:
Lisää oma ohj2-kirjasto ei voi tehdä. Ohjelman voi piirrellä, mutta ei ajaa jos kirjastot puuttuvat.Seuraavan esimerkin tavoitteena on tuottaa valmiilta näyttävä, ajettava ohjelma mahdollisimman vähällä koodinkirjoittamisella. Tällaisen näköiskäyttöliittymän avulla olisi sitten helpompi keskustella esimerkiksi asiakkaiden kanssa.
Alta löydät ohjeet tekstimuodossa sekä videona.
Huom! videolla tehdään “väärän” niminen kontrolleri, se pitäisi olla KerhoGUIController. Käytännössä nimillä ei ole mitään merkitystä, mutta jos niitä vaihtaa luomisen jälkeen, niin niitä esiintyy useassa paikassa ja kaikki pitäisi osata vaihtaa. Tuo GUI on vaan kurssin nimeämistavan mukainen.
Aloitetaan luomalla Eclipseen uusi projekti.
Suositeltavaa on noudattaa ohjelmointikurssin nimeämiskäytänteitä. Korvaa alla olevassa esimerkissä kerho oman projektisi työnimellä ja vesal joko omalla käyttäjätunnuksella tai ryhmänne valitsemalla “projektinimellä”. Muista laittaa kerho samalla tavalla kirjoitettuna kuin mallissa (välillä isolla ja välillä pienellä).
Avaa Eclipse
Avaa valikosta: File / New / Other... / JavaFX / JavaFX Project ja paina ‘Next’
Täytä lomake seuraavasti
kerhoC:\MyTemp\vesal\ohj2\kerho/Users/vesal/ohj2/kerho)jdk-13-JavaFX vaikka tarvittaessa ruksimalla se Use a project specific JRE: ja sieltä oikea JRE.Paina Next, ruksi pois Create Module-info.java file ja sitten Next kunnes olet sivulla, jossa kysytään Application type
Täytä lomakkeen tiedot:
DesktopfxKerhoFXMLjavafx.scene.layout.BorderPaneKerhoGUIViewKerhoGUIControllerFinish
Lisää oma ohj2-kirjasto (jos et ole tehnyt vielä tätä kirjastoa FXGui.jar-ohjeen mukaan, voit ohittaa tämän kohdan ja piirtää käyttöliittymät, mutta et voi ajaa ohjelmaa):
Properties/Java Build PathLibraries-välilehdelleAdd LibraryUser Library ja ruksi ohj2Apply and closeMikroluokissa voi joutua tekemään ohj2-kirjaston, ellei ole valmiina.
Jos olet asettanut Eclipsen varoitukset kurssin suositusten mukaan niin KerhoGUIController.java -tiedosto varoittaa virheestä, koska siinä olevasta luokasta puuttuu sisältö. Tästä pääset eteenpäin ihan vain lisäämällä luokan lohkosulkujen sisään kommenttimerkin: // Samoin valittaa puuttuvista kommenteista alleviivaamalla KerhoGUIController. Mene alleviivatun sanan päälle ja valitse Add javadoc comment. Myös Main luokassa lisää kommentit Main-sanan päältä ja main sanan pääältä. Ja main kommentteihin lisää vielä args jälkeen selitys:
/**
* @param args ei käytössä
*/Mene vasemmalla olevan PackageExplorer -paneelin Main.java -tiedoston nimen päälle ja paina hiiren oikealla: Refactor/Rename ja vaihda nimeksi KerhoMain.java.
Vaihda application.css tiedoston nimeksi kerho.css.
Avaa KerhoMain.java ja vaihda myös siellä application.css tilalle kerho.css . Nyt pitäisi vasemman reunan näyttää seuraavalta:

valitse KerhoMain.java aktiiviseksi ja paina F11 ajaaksesi ohjelman.
Pitäisi aueta ohjelma, jossa on tyhjä dialogi.
Sammuta dialogi ja ehkä kannattaa KerhoMain-tiedostosta vielä poistaa koko rajoitteet 400,400. Eli se 400,400 pois, muuten rivi jää ennalleen.
Mä tahkosin tuota samaa carSample ja tiesin koko ajan, että olin kirjoittanut koodin ihan oikein. Sitten tuo aja java applikaationa jäi mietityttämään, kun pohdin, että se taitaa linkittää samalla ne kirjastot?
—Nyt voit avata SceneBuilderin klikkaamalla hiiren oikealla KerhoGUIView.fxml tiedostoa ja sitten Open with SceneBuilder. Ruutu näyttää tyhjältä, mutta siellä on pohjana yksi BorderPane.
Pitääkö NIMIGuiView.fxml avata src- vai bin-hakemistosta?
VL: itse käsitellään aina vain src hakemiston juttuja.
KerhoMain.java:
package fxkerho;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXMLLoader;
/**
* @author vesal
* @version 13.1.2019
*/
public class KerhoMain extends Application {
@Override
public void start(Stage primaryStage) {
try {
BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("KerhoGUIView.fxml"));
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("kerho.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
/**
* @param args ei käytössä
*/
public static void main(String[] args) {
launch(args);
}
}
KerhoGuiController.java:
package fxkerho;
/**
* @author vesal
* @version 13.1.2019
*/
public class KerhoGUIController {
//
}
Virheviesti:
.fxml-tiedostoa avatessa:
Opening the file with SceneBuilder failed.
Try setting the absolute path to scenebuilder in your the preferences
C:\devel\SceneBuilder\SceneBuilder.exeVirheviesti:
Error occurred during initialization of boot layer
java.lang.module.FindException: Module javafx.web not found
Classpath alla eikä Modulepath?
Properties/Java Build Path/Librariesohj2 Classpath päällemodule-info.java-tiedostoa? Jos on, poista se.Ei näy ohj2 User libraryä
Alleviivaa punaisella javafx.application…
jdk-13-JavaFXProperties/Java Build Path/LibrariesJRE... ja Edit ja hae oikea JDKApply ja Close riittävän monesti.
Mulla siirtää tuon JDK:n jostain syystä Classpathiin ja alleviivaa javafx.applicationin
—HUOM! Projektin teko tuntuu varsin työläältä, mutta onneksi viime kevään kurssilaisista Antti teki asiaan helpotuksen, jolla kaikki saadaan yhdellä kysymyksellä. Eli jatkoa varten lue aikanaan ohjeet tuolta: fxmlpackage.jar.
Kun piirretään harjoitustyön suunnitelma SceneBuilderillä, olisi se hyvä saada mahdollisimman aidon näköiseksi. Valmiilla komponenteilla ei monimutkaisempiin komponentteihin saa näköisdataa, esim. vakiokomponenteilla listat ovat tyhjiä, mikä vaikeuttaa hahmottamista. Tällä kurssilla onkin tarjolla avuksi muokattuja komponentteja, joihin voit syöttää “aidon näköistä” dataa, kuten esim. havainnekuvien jäsenlistauksen.
Toimi seuraavasti (videossa on Import JAR/FXML File..., nykyisin siinä on JAR/FXML Manager)
Kurssia varten on tehty käyttöliittymäkomponentteja sisältävä aliohjelmakirjasto, joka on FXGui.jar-nimisessä tiedostossa. Alla on ohjeet sen asentamiseksi:
c:\MyTemp\\ohj2\jar tai c:\devel\jar hakemistoon. Varmista, että tiedostopääte on latauksenkin jälkeen .jar, eli tiedoston kokonimi on fxgui.jar (jotkin selaimet - lue IE yms - vaihtavat ilman lupaa ladatessa tiedostopäätteeksi .zip jolloin tiedostopääte pitää itse muuttaa: “Nimeä uudelleen” fxgui.zip -> fxgui.jar).Library -sanan oikealla puolella olevaa rattaan kuvaa.JAR/FXML Manager.Library Manager..jar -tiedosto.Import Components.Library Managerin (muista mistä sen saa jatkossa käyntiin).Custom -paneelista.Huom! Uudet komponentit täytyy käydä vielä lisäämässä Eclipsenkin puolella (paitsi jos lisäsit aikaisemmin ohj2-kirjaston, johon ne sisältyvät valmiiksi):
PropertiesJava Build Path ja sen välilehti LibrariesModule ja Classpath, niin klikkaa Classpath-kohtaaAdd External JARs...Huom! Omat komponentit voivat aiheuttaa kaikenlaisia epäyhteensopivuusongelmia. Tyypillisin on se, ettei .fxml-tiedostoa pysty avaamaan SceneBuilderiin Eclipsestä käsin, ratkaisu on avata tiedosto SceneBuilderin kautta. Kts. tämän sivun lopusta lisää.
Erehdyin lataamaan tiedoston ensin IE:llä, joka muutti sen väkisin zip-muotoon eikä asennus tietenkään onnistunut. Chrome suostui lataamaan .jar-muodossa, jolloin homma onnistui.
VL: Sääntö nro 1: Älä koskaan käytä IE:tä :-)
Tämä on tässä vaiheessa enemmänkin “nice to know” -tietoa.
Tapa 1: Poista vanhat ja asenna uudet:
Library -sanan oikealla puolella olevaa rattaan kuvaaJar/FXML managerLibrary manager aukeaaTapa 2: Asenna uudet vanhojen päälle:
Library-hakemiston sijainti. Sijainti voi olla esimerkiksi: C:\Users\Vesa\AppData\Roaming\Scene Builder\Library.jar) vanhan päälle.Seuraavassa ohjeet hieman yksinkertaistetun suunnitelman piirtämiseksi (vastaa harjoitustyön mallin vaiheen 1 kuvaa):

Käyttöliittymän tekemisen yksi lähtökohta on se, että käyttöliittymä mukautuu ikkunan (stage) koon muutoksiin. Siksi tehdessä pitää hieman miettiä minkälaisten pohjakomponenttien (Container) päälle itse komponentteja (Component) laitetaan.
Tässä harjoituksessa ikkunan käyttöliittymän asettelun pohjaksi on valittu BorderPane-niminen container, koska se jakaa mukavasti ikkunan viiteen eri osaan. Kaikkia osia ei ole aina pakko käyttää (tämän harjoituksen 1. vaiheessa käytämme vain neljää) ja container-komponentteja voi sijoittaa sisäkkäinkin.
Ennen kuin aloitetaan rakentelu, niin kurkataan hieman millaista lopputulosta kohti mennään. Seuraavassa kuvassa on näkymä SceneBuilder documentin hierarkiasta kun kaikki komponentit ovat paikallaan:
FXGui.jar -apukomponentit?Libraryn oikeanpuoleisen rattaan alta View as List, jolloin kaikki komponentit näkyvät samassa listassa.Aloitetaan täyttämällä ensin ikkunan reunaosat:
HBoxin avulla
Library/Containers -lista ja etsi HBox (huomaa, että voit käyttää myös hakua)HBox-elementti hiirellä BorderPane-alueen alareunaan (Bottom). Helpointa on raahata elementti vasemmalla olevaan Hierarchy -hierarkianäkymässä olevaan insert BOTTOM-kohtaan, koska itse käyttöliittymän kuva elää hyvin paljon kehityksen aikana mikä aiheuttaa helposti virhesijoituksia.HBox on valittuna ja avaa oikeasta reunasta ´Layout:HBox´Pref Width ja Pref Height koot asetukseen USE_COMPUTED_SIZE.Spacing-kohtaan 10Margin kohtiin 10. Tämä onnistuu helpostin kun laittaa ensimmäiseen 10 ja sitten klikkaa väkästä (>) joka vie saman muihin kohtiinButton):
Library/Controls-listalta Button ja vedä ne luomasi HBoxin päälle.Uusi jäsen ja Tallenna).
Properties:Button/Text TAIMenuBar):
Library/Controls-listalta MenuBar ja raahaa se BorderPane-alueen Top-osaan.MenuBarin rakenteen vasemman reunan Hierarchy-valikosta.BorderPane valintalistaa ja sen otsikkoa varten:
Library/Containers-listalta uusi BorderPane ja raahaa se olemassa olevan BorderPanen Left-osaan.BordePane Hierarchy-näkymässä niin, että näet sen osa-alueet.ListChooser) ja sille otsikko (Label):
Library/Controls-listalta Label, ja raahaa se uuden BorderPane alueen Top-osaan.Jäsenet).FXGui.jar -apukomponentit, etsi Library/Custom-listalta ListChooser ja raahaa se uuden BorderPanen keskiosaan (Center).Properties:ListChooserRivit päälle.Switch to multi-lines mode.Ubuntussa ei pysty ollenkaan raahaamaan asioita librarystä pois. Joskus silloin tällöin saattaa onnistua. Mutta näinkin käydessä objectit menevät ihan minne sattuu eikä sinne, minne halusi.
—Seuraavaksi täytetään keskiosaa, johon pitää saada komponentit niin, että niiden koko muuttuu kun alueen kokoa muutetaan:
BorderPanen keskiosaan vieritettävä ScrollPane (empty) -osio: -Library/Containers: ScrollPane (empty)
Layout:ScrollPane -paneelissa kohtaan Fit to Width, jotta se täyttää kaiken alueen tilanLibrary/Containers: GridPane edellä luodun ScrollPanenpäälle
Layout:GridPane -paneeli ja tee muutokset:
Hgap -kohtaan arvo 10, jotta sarakkeiden väliin tulee sopivasti tyhjää.Padding-kohtiin muihin 10 paitsi alaosaan.Layout: ColumnConstraints-paneelista:
Pref Width -kohtaan USE_COMPUTED_SIZEFill WidthHalignment-kohtaan RIGHT.Layout: ColumnConstraints-paneelista:
Fill Width -kohdassa on ruksiHGROW -kohtaan Always.USE_COMPUTED_SIZE.Label -komponentteja 0-sarakkeen eri riveille ja vaihdetaan niihin sopivat otsikot.
GridPane-komponentin alareunaan TAI klikkaamalla hiiren oikealla napilla rivinumeroa.TextField-komponentit 1-sarakkeen riveille
Library/Controls: TextFieldLayout: TextField: Vaihda HGROW-kohtaan Always. (Videossa tätä ei tarvinnut tehdä, kokeile ilman ja kerro toimiiko!)Kokeillaan toimiiko komponenttien skaalaus: Paina Ctrl+P (Mac: Cmd+P) ja muuttele “ohjelman” kokoa ja katso että TextField pienenee ja kasvaa halutulla tavalla. Samoin katso että ScrollPane alueen vierityspalkki tulee kun kokoa muutetaan riittävän pieneksi.
Sitten vielä lisää loput TextField -komponentit ottamalla kopio alkuperäisestä ja pastea niitä riittävä määrä. Ne voivat mennä väärään ruutuun, mutta raahaa ne siltä paikalleen. Laita kuhunkin TextField -kenttään malliksi sopiva teksti jotta käyttöliittymä näyttää aidommalta.
4. OS X:llä ainakin täytyy asettaa "Hgrow Always", jottei otsikko lähde ajelehtimaan.
—Mac: ei ctrl + P vaan komento + P
—En saa myöskään skaalautumaan oikein, vaikka teen ohjeen mukaan. Tutkin koodia, että mikä menee mulle erilailla, niin minulla koodin tulee labelien ja textfieldin jälkeen <GridPane.margin> < Insets /> </GridPane.margin> Voisiko tämä olla syynä, miksi skaalautuminen ei onnistu? Jos on, mitä pitäisi tehdä?
VL: Katso tuolta KerhoGUIView.fxml miltä mun .fxml näyttää.
Nyt ulkoasun pitäisi olla suunnitelman mukainen. Seuraavaa vaihetta varten vielä pieni viimeistely.
Mitä voi olla pielessä, jos ei skaalaudu oikein?
VL: tähän ei voi kukaan vastata näkemättä itse toteutusta. Virhemakhdollisuuksia on enemmän kuin Päijänteessä kaloja :-)
Vertaa tuohon mun KerhoGUIView.fxml-tiedostoon.
—Luonnollisesti haluamme lisätä käyttöliittymään uusia käyttäjiä helpottavat Tooltipit sekä tottuneita käyttäjiä helpottavia pikavalintoja.
Tooltippien lisääminen:
Ctrl pohjassa ja klikkaile rivinumeroita ja sitten valitse Pref Height kohtaan USE_COMPUTED_SIZE. Huom. Tätä ei kannata tehdä ennen kuin kaikki labelit ovat paikallaan, koska muuten rivit kutistuvat niin pieniksi että niihin on vaikea pudottaa.Tooltip (Miscellaneous) ja raahaa Button-komponentin päälle.Pikavalintojen lisääminen:
Esimerkiksi haluamme että Uusi jäsen-painike aktivoituu painamalla näppäimistöltä Alt-U. Toimitaan seuraavasti:
Uusi jäsen -painikeProperties-paneelista kohta Mnemonic Parsing ja laita siihen ruksi.Properties-paneelin yläosaan ja lisää Text-kentässä painikkeen nimen eteen alaviiva (_Uusi jäsen)Alt on painettuna.Lisätään Tallentaminen valinnalla Ctrl-S:
Tallenna -menu itemProperties-paneelista AcceleratorCONTROL_DOWN,noneS. Hieman hassusti noilla valikoilla ei ole sulkemisnappia, vaan valinta tulee voimaan kun poistut sen alueelta.Lopeta -kohtaan Ctrl-QCtrl-N.Accelerator-kohtaa ei löydy Macilla vai olenko vain itse hukassa?
—Macilla loin MenuBarin ja lisäsin valmiina tulleen Menun (File) alle MenuItem:in, ja esimerkiksi tämän ominaisuuksista accelerator löytyy. Toisaalta esimerkiksi puhtaan Buttonin ominaisuuksissa en accelerator-kohtaa nähnyt.
Kyse ei tässä taida olla eroista käyttöjärjestelmien välillä, ja joka tapauksessa voihan yrittää editoida SceneBuilderin luomaa .fxml-tiedostoa, ja käsin lisätä sinne accelerator.
—VL: Acceleraattoria ei taida olla muuta kuin MenuItem-komponenteille.
Muista tallentaa syntynyt .fxml-tiedosto. Huomioi, että jos omaan ohjelmaan on lisätty pikatoiminto Ctrl-S, niin SceneBuilderin Ctrl-S ei enää toimi, vaan tallennus pitää tehdä menun kautta.
VINKKI: Tämä on hyvä paikka ottaa käyttöliittymästä ruutukaappauksia Harjoitustyön 2. vaihetta varten.
Voit avata alle mallia tehdessä syntyneet tiedostot, joita voit verrata omiisi. Tai voit niitä myös kokeilla muutella ja ajaakin, kunhan painelet noiden Tallenna, Käännä ja Aja-painikkeita järjestyksessä.
Seuraavaksi palaamme takaisin Eclipsen puolelle. Ensin pari vinkkiä, jotka voivat ennakoivasti auttaa näennäisissä vikatilanteissa:
FXML-tiedostojen päivittämisestä: Kun kehitystyössä pompimme Eclipsen ja SceneBuilderin välillä, on meidän syytä huomioida, että välillä Eclipse huomaa automaattisesti SceneBuilderia käytettässä .fxml-tiedostoon syntyneet muutokset ja välillä ei. Saat päivitettyä muutokset klikkaamalla projektin nimen päällä hiiren oikeaa nappia ja valitsemalla Refresh (pikavalintana F5). Elleivät muutokset vieläkään päivity, niin olethan varmasti muistanut tallentaa tekemäsi muutokset SceneBuilderissa?
FXML-tiedostojen tarkastelusta. Kohti edistyeempää käyttöä:* Muistathan, että voit avata .fxml-tiedoston Eclipsellä XML-muodossa ottamalla hiiren oikealla tiedoston nimen päällä ja Open With/FXML editor. Tällöin voit itse varmistua, mitä muutoksia tiedostoon syntyy, kun muokkaat sitä SceneBuilderissa. Huomaa, että voi tehdä muutoksia myös suoraan tekstieditorissa – se voi tuntua alkuun hieman vieraalta, mutta on pohjimmiltaan aika yksinkertaista.
Varmistetaan, että ohjelma käynnistyy: Avaa Eclipsessä KerhoMain.java ja kokeile ajaa se (F11).
Jos saat virheen puuttuvasta ListChooser-komponentista, niin et ole vielä kertonut Eclipselle, että käytössämme on omia komponentteja. Ohjeet löytyvät yllä olevalta videolta, mutta lyhyesti summattuna:
PropertiesJava Build Path ja sen välilehti LibrariesAdd External JARs...fxgui.jar-tiedoston tallentanut. Voit käyttää myös sitä Library paikkaa SceneBuilder sen tallensi.File/Open)Kommentit kuntoon. Hyvän tavan ja kurssin vaatimusten mukaisesti laitetaan kommentit kuntoon. Aloita kommentoimalla KerhoMain.java -tiedostossa itse luokka ja main-metodi: Kirjoita yläpuolelle
/**
ja paina return. Tällöin Eclipse täydentää kommenttien pakolliset osat ja voit itse täydentää ne loppuun.
Siirrytään varsinaiseen toiminnallisuuksien lisäämiseen:
Kutsuttavien metodien lisäys. Jotta graafiseen käyttöliittymään luomamme painikkeet tekisivät jotain Java-ohjelmassamme, meidän täytyy Eclipsessä lisätä KerhoGUIController.java-tiedostoon metodeja, joita painikkeet kutsuvat. Lisätään ensin koodi:
Avaa Eclipsessä KerhoGUIController.java-tiedosto ja lisää KerhoGUIController-luokan sisään metodeja tyyliin:
package fxKerho;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import java.net.URL;
import java.util.ResourceBundle;
import fi.jyu.mit.fxgui.*;
/**
* Luokka kerhon käyttöliittymän tapahtumien hoitamiseksi.
* @author vesal
* @version 3.1.2018
*/
public class KerhoGUIController implements Initializable {
@Override
public void initialize(URL url, ResourceBundle bundle) {
//
}
/**
* Käsitellään uuden jäsenen lisääminen
*/
@FXML private void handleUusiJasen() {
Dialogs.showMessageDialog("Ei osata vielä lisätä");
}
/**
* Käsitellään tallennuskäsky
*/
@FXML private void handleTallenna() {
tallenna();
}
/**
* Käsitellään lopetuskäsky
*/
@FXML private void handleLopeta() {
tallenna();
Platform.exit();
}
/**
* Tietojen tallennus
*/
private void tallenna() {
Dialogs.showMessageDialog("Tallennetetaan! Mutta ei toimi vielä");
}
}
Metodikutsujen lisäys SceneBuilderissa Seuraavaksi lisäämme SceneBuilderissa painikkeille ja valikoille ohjeet, että mitä koodissa olevaa metodia kukin niistä kutsuu:
Avaa taas SceneBuilder:
Uusi jäsen -painike.Code-paneelista kohta On Action@FXML-merkityt metodit: Valitse tässä tapauksessa handleUusiJasen – tämä on siis metodi, jonka lisäsimme juuri edellä koodiin.
On Action-kenttään risuaita ja metodin nimi, esim.: #handleUusiJasenKerhoGUIView.fxml-tiedostoa silmäilemällä, että homma meni oikein. Siellä pitäisi olla rivi tyyliin (rivillä voi olla myös muita attribuutteja, jos niitä on määritelty):<Button onAction="#handleUusiJasen" text="Uusi jäsen">
En saa Macilla näkyviin mitään alasvetovalikkoa?
—Näköjään voi vain kirjoittaa input-kenttään "#handleUusiJasen".
—Palaa Eclipseen ja kokeile ajaa ohjelma. Nyt ohjelman pitäisi reagoida menuihin ja painikkeisiin.
Menuvalintaan lisätyn Lopeta-kohdan kautta ohjelma kyllä kiertää tallenna-metodin kautta kun ohjelma lopetetaan sitä kautta, mutta mikäli ohjelma suljetaan esim. painamalla Windowsissa ikkunan oikean ylänurkan ruksia, onnistutaan kiertämään tallennusvaihtoehdot. Tämän korjaaminen on tehty lievästi haastavaksi JavaFX:ssä, mutta onnistuu start-metodia muokkaamalla:
Ongelma: Ikkunan sulkeminen ohittaa tallennuksen.
Ratkaisu: Muokataan KerhoMain.java-tiedoston sisältämää start-nimistä käynnistysmetodia. Tarvittava koodi on luotu sinulle alle jo valmiiksi - meidän ei tarvitse nyt syventyä siihen sen tarkemmin, mutta muutoksen tarkoituksena on, että kun KerhoGUIView.fxml-tiedosto luetaan ja siitä muodostetaan käyttöliittymä ja luodaan controller-luokka, niin samalla otetaan tuo controller-luokan viite talteen.
Muutos start-metodiin: Kopioi siis alla olevan koodin oman ´start´-metodisi päälle, mutta muista korjata kaikki viittaukset projektin tiedostoihin, nimiin ja muuttujiin niin että ne vastaavat omaasi - käy koodi läpi ja sinun pitäisi tunnistaa jotakuinkin 6 korjattavaa kohtaa. Nyt on hyvä tilaisuus harjoitella koodin kommentointia, jotta löydät tekemäsi muutokset jos myöhemmin huomaat tehneesi virheen.
Myös pitää lisätä import riveihin (vastaava BorderPane-rivi voi muuttua tarpeettomaksi):
import javafx.scene.layout.Pane;
koska tuolla viitataan luokkaan Pane. Kohti edistyneempää käyttöä: Voit toki vertailla omaa ja allaolevaa koodia ja tehdä tarvittavat muutokset rivi kerrallaan – siinä samalla jää ehkä paremmin muistijälkiä metodin rakenteesta :)
public void start(Stage primaryStage) {
try {
FXMLLoader ldr = new FXMLLoader(getClass().getResource("KerhoGUIView.fxml")); // korjaa tiedostonimi
final Pane root = (Pane)ldr.load();
final KerhoGUIController kerhoCtrl = (KerhoGUIController)ldr.getController(); // korjaa nimet
final Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("kerho.css").toExternalForm()); // korjaa tiedostonimi
primaryStage.setScene(scene);
primaryStage.setTitle("Kerho"); // korjaa title
// Platform.setImplicitExit(false); // jos tämän laittaa, pitää itse sulkea
primaryStage.setOnCloseRequest((event) -> {
// Kutsutaan voikoSulkea-metodia
if ( !kerhoCtrl.voikoSulkea() ) event.consume(); // korjaa nimi
});
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
Dokumentissa JavaFX/kaytto on kuvattu tarkemmin mitä mikäkin rivi edellä tarkoittaa. Tässä vaiheessa voidaan toki vielä mennä ajatuksella “nuo siinä pitää olla”.
Mitä tapahtui? Metodiin start lisättiin kuuntelija sille, että kun käyttäjä haluaa sulkea ohjelman, niin ohjelma kysyy controller-luokan metodilta voikoSulkea, että saako ohjelman sulkea vaiko ei. Mikäli metodi vastaa “ei saa”, niin poistetaan sulkemistapahtuma jonosta ja estetään sulkeminen. Nyt controller-luokka voi itse päättää salliiko se ohjelman sulkeutumisen ja samalla tallentaa tiedot jos haluaa. Mutta meiltähän vielä puuttuu se voikoSulkea-metodi, jota nyt kutsumme, joten…
Lisätään voikoSulkea-metodi. Seuraavaksi meidän täytyy luoda edellä luotuun kutsuun vastaava metodi. Sen sijoitamme KerhoGUIController.java-tiedostossa esiteltyyn KerhoGUIController-luokkaan, siis sinne minne aikaisemmin loimme tapahtumakäsittelijöitä. Lopullisessa ohjelmassa metodi tekisi erilaisia tarkastuksia, mutta tässä vaiheessa pärjäämme yksinkertaisella koodilla, jonka voit kopioida alta:
/**
* Tarkistetaan onko tallennus tehty
* @return true jos saa sulkaa sovelluksen, false jos ei
*/
public boolean voikoSulkea() {
tallenna();
return true;
}
Myöhemmin tehtäviä muutoksia: Tulevaisuudessa tässä metodissa tietysti tarkistetaan onko tallentamiselle tarvetta ja jos on, niin kysytään käyttäjältä mitä hän haluaa tehdä.
(Mac) Hmm. Mikäköhän on kun Eclipse ei enää käynnistä sovellusikkunaa. Säen kyllä, että jokin Java-ohjelma käynnistyy, mutten näe ikkunaa. en pysy edes sulkemaan sitä muutoin kuin "Pakota lopettamaan" -valikosta (cmd+alt+esc).
- VL: vaikuttaisi siltä, että jostakin syystä se ei onnistu näyttämään sitä sovelluksen pääikkunaan? Vaihtoehtoja on niin monta että ei oikein osaa sanoa muuta, kuin että "peruuttaa" siihen kohtaan kun vielä toimi ja katsoo mikä katkaisi kamelin selän.
Usein vikana voi olla se, että FXML-tiedostossa on esim. controller-luokan nimi väärin, se pitää olla täsmälleen oikein paketin nimen ja luokan nimen suhteen. Eli mallissa tuo rivi:
Voit katsoa miltä tiedostot näyttävät tämän vaihen jälkeen.
Alta löydät vinkkejä dialogien luomiseen harjoitustyön suunnitelmaa (ja myös itse harjoitustyötä varten). Kokeile esimerkiksi ajaa seuraava yksinkertaisen dialogin luova ohjelma:
Please
//
// Kun tarvitsee kysyä Kyllä/Ei tyyppisiä kysymyksiä:
boolean vastaus = Dialogs.showQuestionDialog("Poisto?",
"Tallennetaanko", "Kyllä", "Ei");
// if ( vastaus ) tallenna(...Terminologiakertaus: “Dialogilla” tarkoitetaan ikkunoita, jotka haluavat käyttäjältä jonkin syötteen, olipa se sitten napin painallus tai tekstiä. Dialogi-ikkunat voidaan jakaa modaalisiin (mikään ei etene, ennen kuin käyttäjä on vastannut siihen) ja ei-modaalisiin (syöte ei ole pakollinen tai käyttäjän annetaan käyttää samalla muita toimintoja, myös ohjelman työkalupaneelit ovat ei-modaalisia dialogeja). Suppeimmillaan dialogi kostuu yhdestä painikkeesta (esim. kuitataan pop-up -huomautus virheestä), laajemmillaan täytetään kokonaista lomaketta.
Pitäisi tehdä dialogi, joka on vähän saman tyyppinen kuin tuo malli HT:n lisää harrastus dialogi. Ja olin tehnyt jo yhden“ei-yksinkertaisen” dialogin tuolla new FXML Document- kautta, ja ei ongelmia, mutta nyt ei suostu lisäämään uutta. Toisiin fx projekteihin lisää, muttei suostu enää tuohon HT:hen. Ei vain tapahdu mitään kun olen nimennyt tiedoston ja painan finish. Mikäköhän siinä voisi olla?
Edit: ei enää mitään.
—Yksinkertaisten dialogien lisäämisestä: Hyvin yksinkertaisia dialogeja varten ei itse kannata koodia koodia kirjoittaa, koska niitä löytyy JavaFX:stä valmiina ja myös lisäämästämme FXGui-kirjastosta vielä helpommin. Suositeltavaa on tutustua TIM:issä olevaan JavaFX-dialogeja käsittelevään sivuun, josta löydät ohjeita ja mikä parasta: valmista koodia, jota voit muokata ja testata suoraan TIM:issä! Huomaa, että TIM tulostaa dialoginäkymiä kuvina, joita voit hyödyntää harjoitustyösuunnitelmasi liitteenä! Vaihda em. sivulla oleviin esimerkkikoodeihin oman työsi vaatimia tekstejä ja kaappaa sitten kuvia. Otsikkopalkkia ei tule TIMissä oleviin dialogeihin, mutta siitä ei tarvitse tässä vaiheessa huolestua.
Monimutkaisempien dialogien lisäämisestä: Mikäli suunnitelmassasi on useampia “ei yksinkertaisia” dialogeja, voit lisätä niitä projektiisi seuraavalla tavalla:
packagen nimen (esimerkissä fxKerho) päällä:New/Other.../JavaFX/New FXML Document/NextTulostusViewCtrl-P:llä (Mac Cmd-P) ja kaappaa kuva suunnitelman dokumenttia varten.Varsinaista suunnitelmaa varten tarvitaan enemmän komponentteja.
Kerho-esimerkissä lisätään harrastuksia varten StringGrid ja sitten muutama muu omatekoinen ikkuna. Varsinainen pääikkuna jaetaan keskeltä kolmeen osaan, joiden rajaa voidaan siirtää. Tähän käytetään SplitPane -containeria.
Seuraavassa kuvassa on näkymä SceneBuilder dokumentin hierarkiasta täydellisemmässä suunnitelmassa kun kaikki komponentit ovat paikallaan:

KerhoGUIView.fxml
064 <center> 065 <SplitPane dividerPositions="0.27, 0.66" BorderPane.alignment="CENTER"> 066 <items> 067 <BorderPane maxWidth="150.0" minWidth="100.0" prefWidth="138.0"> 068 <center>
Voit katsella edellä olevaa tiedostoa kokonaisena klikkaamalla oikeassa alakulmassa pienellä olevaa nimeä. Tai voit ladata sen SceneBuilderillä avattavaksi klikkaamalla oikealla ja valitsemalla linkin tallennuksen.
Voit katsoa miltä tiedostot näyttävät tämän vaihen jälkeen.
Uutta suunnitelmaa varten tarvitsemme keskelle SplitPanelin jolla voidaan jakaa keskiosan aluetta käyttäjän tarpeiden mukaan eri kokoisiin osiin. Ohjeissa siirrellään aluksi valmiita kokonaisuuksia pois tietä, jotta saadaan BorderPanen keskiosa käyttöön. SceneBuilderissä voi myös luoda paneelin komponentin alle painamalla hiiren oikeaa ja Wrap in, jolla osin voisi kiertää tuota siirtämisen ongelmaa.
Keskiosan alueen jakaminen kolmeen osaan:
BorderPanen oikeaan reunaan uusi BorderPane.Label jossa lukee Jäsenen tiedot.BorderPanesta layoutista kaikki koot lasketuiksi.ScrollPane, jossa on GripPane jäsenen tietojen BorderPanen keskelle.BorderPanen nyt vapaaseen keskiosaan SplitPane (empty).BorderPane SplitPanen päälle.BorderPanelle rajat joissa sen koko voi liikkua:
Layout/Min Width: 100Layout/Perf Width: 138Layout/Max Width: 160BorderPane SplitPanen päälle.SplitPanen päälle yksi BorderPane harrastuksia varten.Splitpanen koot lasketuiksi.Label jossa lukee Jäsenen harrastukset.BorderPanen keskellä Custom-kohdasta StringGrid.StringGrid komponentin Rivit ominaisuuteen muodossa (ensin kannattaa valita vieressä olevasta rattaasta Switch to multine mode, joskus tämä näkyy ja joskus ei, jos valinnat ovat näkymättömiä, on tämä alin niistä):ala|aloitusvuosi|h/vko
kalastus|1955|20
laiskottelu|1950|20
työn pakoilu|1952|40
SplitPanen rajoja sopivasti. Jakokohdat näet numeerisena ominaisuudesta Divider PositionsCtrl-P:llä miten skaalautuu kun kokoa muutetaan.Pitäisikö kohdassa 8 olla ScrollPane BorderPanen sijaan? – Muokkaus: Ei kun ei sittenkään, ymmärsin jotenkin väärin...
—StringGridin palstojen leveyttä olisi kiva sovittaa tekstimäärää vastaavaksi (itsellä esim yhdelle palstalle tulee vain harjoituksen “numero-id”, eli hyvin vähän kirjaimia). SceneBuilder tarjoaakin, että palstojen kokoa voisi hiirellä raahata. Kun näin tekee, SceneBuilder menee Not responding-tilaan, eikä tästä toivu vaan SB pitää sulkea. Tällöin SB ilmoittaa
"OpenJDK Platform binary is not responding
If you close plaa plaa..."
En ole löytänyt layout-valikosta (tai muistakaan) missä palstojen leveyttä voisi säätää.
VL: Niitä voi aikanaan muuttaa ohjelmakoodista, ei tuossa suunnitteluaikana: https://tim.jyu.fi/view/kurssit/tie/ohj2/tyokalut/JavaFX/fxgui/StringGrid#sarakeiden-luominen
Tää StringGrid kaataa eclipsen koko ajan edit: Taitaa olla sama homma ku ylempänä, eli kaatuu kun yritän palstojen leveyttä muuttaa
—
Lisätään seuraavaksi vielä jäsenlistan päälle hakuehdot:
Label Jäsenet oman BorderPanensa alareunaan.BorderPanen yläreunaan VBoxVBoxin kaikki koot lasketuiksi.Label jossa lukee HakuehtoCustom-kohdasta ComboBoxChooser ja kirjoita sen Rivit ominaisuuteen samat tekstit jotka ovat Jäsenen tiedot kohdassa otsikoina, eli nimi, hetu jne.TextFieldJäsenet-label VBoxiin.Layout/Max Width: 300Properties/Node/Alignment: CenterComboBoxChooserille: Layout/Max Width: 300textFieldille vaihda kaikki koot lasketuiksi jolleivat jo ole.Scenebuilder kaatuu myös kun yrittää ComboBoxChooserin riveihin yrittää kirjoittaa
vl; vaikuttaako jos käynnistää sb;n suoraan ilman eclipseä?
edit : Joo näin sai homman toimimaan
Laitetaan alareunaan 4 painiketta kahdesa ryhmässä. Tätä varten lisätään BorderPane, jonka laidoille laitetaan HBoxit joissa painikkeet ovat:
HBox uloimman BorderPanen oikeaan reunaan.BorderPaneen alareunaan uusi BorderPane. Koot lasketuiksi.HBox alareunan BorderPanen vasempaan reunaan.HBox. Koot lasketuiksi. Katso muut asetukset alkuperäisestä HBoxista.HBoxiin painikkeet Lisää harrastus ja Poista harrastus.Muokkaa menun alle.Esimerkiksi tämä viimeinen muutos olisi voitu tehdä myös niin, että valitaan ensin HBox ja sitten hiiren oikella Wrap In ja sieltä valitaan BorderPane. Oletuksena olisi mennyt väärään osaan (alaosaan), mutta sieltä on helppoa raahata HBox vasempaan reunaan. Sitten olisi jatkettu kuten yllä.
Erikseen piirrettyjen dialogien näyttäminen vaatii jo ohjelmakoodia. Sitä voit katsoa malliharjoitustyön vaiheesta 3:
.fxml-tiedostolle ja tietysti vastaavasti liitetty siellä paikalleen.handleTietoja miten AboutView.fxml näytetään kun Tietoja-valintaa klikataanhandleTulosta kutsutaan itse tehdyn luokan (lisätty ihan uusi Class Ecplipsessä) TulostusController staattista metodia tulosta.fxml -tiedostoon.Komponenttien värien muuntelu kannattaa tehdä tyylitiedostojen avulla. Tyylitiedoston näet Eclipsessä .css-päätteisenä tiedostona - tämän harjoituksen esimerkissä se olisi kerho.css.
CSS-tyyliohjeet ovat ehkä osalle tuttuja WWW-suunnittelusta.
Löydät lisäohjeita tyylitiedostojen käyttöön JavaFX:n käyttöä käsittelevästä TIM-dokumentista.
Jotta käyttöliittymään lisätyt kuvat näkyisivät sekä SceneBuilderissa että ajettavassa JAR-tiedostossa, kannattaa kuvat sisältävä hakemisto siirtää sen paketin sisään, jossa käyttöliittymän FXML-tiedostot sijaitsevat (yleensä fxHarkannimi-niminen paketti).
Jos olet ennen tätä ehtinyt jo lisätä kuvia SceneBuilderissa poimien kuvat jostain muualta, niin näiden kuvien polut täytyy korjata muotoon
<Image url="@kuvat/jokukuva.png" />
jossa kuvat-hakemisto sijaitsee fxHarkannimi-paketissa. Kuvahakemisto voi sisältää alihakemistojakin.
Nämäkin?
—Tuon linkin takana oli sen verran hyödyllisiä juttuja, että niiden olisi ehkä ollut hyödyllistä olla (jossain muodossa) osa demoja. Löysin vasta itse koko sivun, ja nyt tuntuu, että aikaa (harkkatyön takia) niiden tekemiseen ei ole, vaikka mallia voikin olla hyödyllistä tuolta katsoa.
EDIT: Tuossa lukee, että on ollut osana demoja… meni kyllä ainakin itseltä ihan ohi. Ehkä nuo tehtävät olisivat voineet olla pilkotusti osa useampaa demoviikkoa.
VL: ne oli. Niitä sai tehdä usealla kerralla ja lopulta ne oli pakollisena…
Tein minä JavaFX tehtäviäkin demoilla, mutta ehkä jäi huomaamatta tuo Autolaskuri ja oman komponentin teko demoviikoilla.
—Ongelma: Monesti erityisesti mikroluokissa omia komponenttikirjastoja käyttävien .fxml-tiedostojen uudelleenavaamisessa Eclipsen kautta tulee ongelmia, ja SceneBuilder näin avattuna kaatuu.
Ongelma: Kurssin omien komponenttien käyttö vaikuttaisi monissa tapauksissa johtavan tilanteeseen, jossa .fxml-tiedostoa ei enää pysty aukaisemaan Eclipsestä käsin SceneBuilderiin.
File/OpenComboBoxChooserin kanssa on allekirjoittaneella myös sellainen ongelma, että jos SceneBuilderin preview-tilassa klikkaa sen auki, niin koko SceneBuilder lakkaa vastaamasta saman tien. Muilla samoja ongelmia?
- VL: voisitko lähettää sen .fxml-tiedoston tutkittavaksi. Mikä käyttis?
Jos ListChooserin laittaa GridPanelin sisään ja laittaa ListChooserille marginia, niin tallennuksen jälkeen SceneBuilder ei enää suostu avaamaan tiedostoa ennen kuin poistaa fxml-tiedostosta margin-tagin:
- tässä täytyy olla joku ajoitusongelma, eli SceneBuilder ei ehdi ladata kirjastossa olevia .jar tiedostoja ennenkuin itse .fxml-tiedosto on avattu (???).
Kas. Olisi pitänyt lukea sivun loppuun. Meni aika kauan ongelman kanssa tapellessa…
—<GridPanel.margin>
...
</GridPanel.margin>
Ongelma saattaa ilmaantua myös muiden kuin GridPanelin kanssa. Ja ilmeneekin monella muulla tavalla ja tuo SceneBuilderin avaaminen ensin erikseen ja sitten File/Open ja etsii muokattavan .fxml-tiedoston.
View/Show Sample Controller Skeleton.Copy.These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.