Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

De interaktive komponentene har en felles måte å rapportere hva brukeren gjør, gjennom såkalte hendelser (eng: event). Hendelsene kan fortelle om både elementære ting (såkalte leksikalske hendelser) som at muspekeren flyttes eller at en tast trykkes ned, eller mer høynivå ting (såkalte syntaktiske hendelser) som at en knapp trykkes, meny- eller liste-element velges, tekst redigeres osv. For å motta en hendelse, så må applikasjonen registrere såkalte lyttere, dvs. objekter som implementerer spesifikke lytter-grensesnitt og som får beskjed om hendelsene ved at spesifikke metoder kalles.

Lyttere kan registreres på en komponent på to måter:

generell addEventHandler-metode - denne tar inn en hendelsestype og lytter-objektet og registrerer lytteren for den angitte hendelsestypen, f.eks. addEventHandler(ActionEvent.ACTION, actionEventHandler)

spesielle setOnXXX-metoder - disse er for spesifikke hendelsestyper og tar inn en lytter og registrere den for denne hendelsestyper, f.eks. setOnAction(actionEventHandler)

I eksemplet under har vi lagt inn et tekstfelt i topp-regionen og reagerer på return ved å kopiere teksten i tekstfeltet inn i Text-objektet i midt-regionen.

Det er to hovedkategorier hendelser, interaksjonshendelser og dataendringshendelser, og disse bruker hver sine lyttergrensesnitt og metoder for å registrere lyttere. La oss ta et tekstfelt som eksempel, siden rapporterer hendelser av begge typer:

Interaksjonshendelsen "action"

Når brukeren trykker return (for å angi at teksten er ferdigredigert), så genereres en interaksjonshendelser kalt "action" av typen ActionEvent. Denne rapporteres til grensesnittet EventHandler<ActionEvent> og metoden handle(ActionEvent). I praksis betyr dette at grensesnittet med tilhørende metode må implementeres av et objekt, og dette objektet må registreres som lytter. Det vanlige er at lytteren implementeres vha. en såkalt anonym indreklasse, som enkelt sagt er et enkeltobjekt som implementerer grensesnittet uten at en eksplisitt må opprette og navngi en ny klasse. I dette tilfellet gjøres det med følgende kode:

Code Block
new EventHandler<ActionEvent>() {
	@Override
	public void handle(ActionEvent actionEvent) {
		... her er selve koden ...
    }
}

Denne lytter(grensesnitt-instans)en oppgis direkte som argument til metoden som registrerer lytteren. Det finnes to (typer) metoder som brukes til dette:

  • en generell addEventHandler-metode, som tar inn en hendelsestype og lyttereren, i dette tilfellet addEventHandler(ActionEvent.ACTION, new EventHandler<ActionEvent>() {... });
  • spesielle setOnXXX-metoder, som brukes for spesifikke hendelsestyper og tar inn en lytter, i dette tilfellet setOnAction(, new EventHandler<ActionEvent>() {... })

I koden nedenfor har vi brukt setOn-varianten, siden den er enklest å lese og skrive.

Dataendringshendelse for "text"-egenskapen

Mens brukeren redigerer teksten i et tekstfelt, så genereres det kontinuerlig (for hver enkelt-endring) en dataendringshendelser for "text"-egenskapen (eng: property) til tekstfeltet. En slik egenskap kan ses på som en verdi (i dette tilfellet en String) som er innkapslet av et objekt som lar en lese, endre og lytte til endringer. Dette er en generell teknikk som brukes av alle dataorienterte komponenter, for å bruke og redigere data. Denne typen hendelser rapporteres til grensesnittet ChangeListener spesialisert til typen data, i dette tilfellet ChangeListener<String> og metoden changed. Også her er det praktisk å bruke enkeltobjekter som implementerer grensesnittet, i dette tilfellet følgende kode:

Code Block
new ChangeListener<String>() {
	@Override
	public void changed(ObservableValue<? extends String> property, String oldValue, String newValue) {
		... her er selve koden ...
	}
}

Denne lytter(grensesnitt-instans)en oppgis (som over) direkte som argument til metoden som registrerer lytteren. Metoden er en del av objektet som innkapsler String-verdien, så følgende kode brukes: textProperty().addListener(new ChangeListener<String>() {... }); textProperty()-kallet returnerer text-egenskapen og det er denne som registrerer lytteren med addListener.

I eksemplet under har vi kombinert både interaksjonshendelser og dataendringshendelser for et tekstfelt i topp-regionen. Hvor hver redigering så kopieres teksten i tekstfeltet til Text-objektet i midt-regionen, og når brukeren trykker return, så gjøres denne teksten om til store bokstaver.

Code Block
    @Override
    public void start(Stage stage) throws Exception {
        
        BorderPane root = new BorderPane(); // Root of the scene graph
        
        textField = new TextField("center");
        textField.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent arg0) 
Code Block
    @Override
    public void start(Stage stage) throws Exception {
        
        BorderPane root = new BorderPane(); // Root of the scene graph
centerText.setText(textField.getText().toUpperCase());
            }
        textField = new TextField("center"});
        textField.setOnAction		textField.textProperty().addListener(new EventHandler<ActionEvent>ChangeListener<String>() {
            @Override
            public void handle(ActionEvent arg0changed(ObservableValue<? extends String> value, String oldText, String newText) {
                centerText.setText(textField.getText());
            }
        });
        		centerText = new Text(180, 180, textField.getText()); // x, y, text
        
        root.setTop(textField);
        root.setBottom(new Text("bottom"));
        root.setLeft(new Text("left"));
        root.setRight(new Text("right"));
        Pane shapesPane = new Pane();
        shapesPane.setPrefSize(300, 300);
        Line line = new Line(10, 10, 100, 100); // x1, y1, x2, y2
        line.getStrokeDashArray().setAll(10.0d, 10.0d); // dashes
        Rectangle rect = new Rectangle(150, 10, 30, 40); // x, y, w, h
        rect.setFill(Color.BLUE);
        Ellipse ell = new Ellipse(40, 180, 40, 30); // cx, cy, rx, ry
        ell.setStroke(Color.RED);
        ell.setStrokeWidth(5);
        ell.setFill(Color.GREEN);
        centerText = new Text(180, 180, "center");
        List<String> fonts = Font.getFamilies();
        centerText.setFont(new Font(fonts.get((int) (Math.random() * fonts.size())), 32));
        shapesPane.getChildren().addAll(line, rect, ell, centerText);
        root.setCenter(shapesPane);
        
        Scene scene = new Scene(root, 500, 500);
    
        stage.setScene(scene);
        stage.setTitle("BorderPaneApplication");
        stage.show();
    }

...