- COMP.CS.140
- 12. Graafiset käyttöliittymät
- 12.2 JavaFX-kirjasto
- 12.2.2 Ensimmäinen JavaFX-ohjelma
Ensimmäinen JavaFX-ohjelma¶
JavaFX-ohjelma koostuu kahdesta keskeisestä säiliöstä (engl. container): stagesta eli näyttämöstä (engl. stage) ja skenestä eli maisemasta (engl. scene).
Stage
on ylimmän tason säiliö eli se esittää koko ikkunaa.Scene
on säiliö, joka sisältää kaiken ikkunassa esitettävän sisällön.
Skenen sisältö koostuu ruudun sisällöstä.
Ruudulle piirrettävät elementit (engl. node) lisätään juurielementtiin, esim. StackPane
tai FlowPane
, joka määrittää niiden sijainnin ruudulla.
JavaFX-ohjelma, jossa tapahtuma, on yksinkertaisimmillaan siis:
package example;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage stage) {
// Luodaan käyttöliittymään nappula
Button printButton = new Button();
// ja sille teksti "Print"
printButton.setText("Print");
// Luodaan lisäksi tekstikenttä
TextField output = new TextField();
// ja sille toivottu leveys pikseleinä
output.setPrefWidth(250);
// Luodaan näyttöelementeille ruutu (engl. pane)
// FlowPane asettaa elementtinsä vaakaan tai pystyyn,
// oletuksena vaakaan
var group = new FlowPane();
// Lisätään elementit ruutuunsa
group.getChildren().add(printButton);
group.getChildren().add(output);
// voi lisätä myös useamman kerralla group.getChildren().addAll(printButton, output);
// Luodaan skene ja lisätään luotu ruutu siihen.
Scene scene = new Scene(group, 300, 150);
// lisätään skene stagelle
stage.setScene( scene );
stage.setTitle("All the world's a stage");
// ja näytetään se
stage.show();
}
public static void main(String[] args) {
launch( args );
}
}
Tässä kohtaa ohjelmamme näyttää tältä:
Ohjelmamme ei kuitenkaan vielä tee mitään eli meidän pitää lisätä tapahtumakäsittelijä nappulallemme.
Tapahtuma käsitellään rajapinnan EventHandler
toteuttamalla oliolla.
Nappulan painalluksen tyyppi on ActionEvent
.
Lisätään koodiin ennen scenen luomista tapahtumakäsittelijä nappulalle printButton
:
// tapahtumakäsittelijä määritellään aina käyttöliittymäelementille
// se kertoo, mitä toiminnallisuutta tapahtuman tapahtuessa tarvitaan
// tässä napin painallus kirjoittaa tekstikenttään tekstiä näkyviin
printButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
// Huom! olioiden, joita käytetään käsittelijässä,
// tulee olla määriteltyjä ennen käsittelijän toteutusta
output.setText("And all the men and women merely players;");
}
});
Kun käyttöliittymäelementti, johon tapahtumakäsittelijä on liitetty, suorittaa jonkin toiminnon, elementtiin liitetty tapahtumakäsittelijä suoritetaan. Nyt ohjelmamme näyttää nappulan painalluksen jälkeen:
Tapahtumakäsittelijä voidaan halutessa määritellä lambda-funktiolla:
printButton.setOnAction((event) -> {
output.setText("And all the men and women merely players;");
});
Kuten aiemmin todettiin tapahtumakäsittelijän tyyppi riippuu käyttöliittymäelementistä, johon se liitetään.
Näppäimen painallusta käsittelee KeyEvent
, jolloin tekstikentän enterin painalluksella tyhjentävä tapahtuma saataisiin
lisäämällä nappulalle käsittelijä:
printButton.setOnKeyPressed( new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent k) {
if (k.getCode().equals(KeyCode.ENTER)) {
output.clear();
}
}
});
Lisäksi, jos halutaan tarkkailla muutoksia jonkin elementin jossain ominaisuudessa, siihen voidaan liittää changeListener
tapahtumakäsittelijäksi.
Esimerkiksi liukuvalitsimen arvon muutoksia kuunneltaisiin slider.valueProperty.addListener( new ChangeListener<Number>)
-käsittelijässä, jossa
toteutettaisiin @Override public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue)
Ohjelmointidemo (kesto 16:01)