You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Next »

Dette eksemplet viser hvordan man kan skriver Java-kode koblet til en FXML-fil med skjermbilde-innholdet.

I dette programmet trenger vi to filer: FXML-fila med skjerminnholdet og Java-fila med koden som er koblet til FXML-en. Jeg har tegnet bildet med Scene Builder, og justerte litt på FXML-en i editoren etterpå, for å legge til et punkt i Polygon-objektet (som først var en trekant). Bildet ser du under til venstre, og FXML-koden er til høyre. Hvis du kopierer FXML-koden inn i Eclipse og åpner Preview-panelet med Window->Show view->Other..., så vil du se det samme bildet.

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.*?>

<AnchorPane prefHeight="284.7071075439453" prefWidth="246.7071083188057" xmlns:fx="http://javafx.com/fxml">
  <!-- TODO Add Nodes -->
  <children>
    <Button fx:id="trykkHerKnapp" layoutX="69.0" layoutY="4.0" mnemonicParsing="false" onAction="#handleTrykkHer" text="Trykk her!" />
    <Line endX="50.0" endY="73.0" layoutX="129.0" layoutY="60.0" startX="49.0" startY="149.0" />
    <Circle fill="WHITE" layoutX="179.0" layoutY="103.0" radius="30.0" stroke="BLACK" strokeType="INSIDE" />
    <Line endX="8.0" endY="-20.0" layoutX="169.0" layoutY="171.0" startX="-42.0" startY="-13.0" />
    <Line endX="1.0" endY="-30.0" layoutX="179.0" layoutY="181.0" startX="41.0" startY="-13.0" />
    <Line endX="1.0" endY="-30.0" layoutX="177.0" layoutY="240.0" startX="41.0" startY="-13.0" />
    <Line endX="8.0" endY="-20.0" layoutX="169.0" layoutY="230.0" startX="-34.0" startY="1.0" />
    <Ellipse fill="DODGERBLUE" layoutX="29.0" layoutY="150.0" radiusX="14.20709228515625" radiusY="80.0" stroke="BLACK" strokeType="INSIDE" />
    <Ellipse fill="RED" layoutX="29.0" layoutY="150.0" radiusX="9.20709228515625" radiusY="29.999984741210938" stroke="BLACK" strokeType="INSIDE" />
    <Polygon fx:id="kniv" fill="#dfdfdf" layoutX="101.0" layoutY="158.0" stroke="BLACK" strokeType="INSIDE">
      <points>
        <Double fx:value="-40.0" /><Double fx:value="0.0" />
        <Double fx:value="20.0" /><Double fx:value="20.0" />
        <Double fx:value="50.0" /><Double fx:value="10.0" />
        <Double fx:value="0.0" /><Double fx:value="-10.0" />
      </points>
    </Polygon>
  </children>
</AnchorPane>

Litt om FXML-en

De fleste linjene tilsvarer en liten del av bildet. F.eks. er hodet en sirkel som lages med Circle-elementet. Plasseringen styres av layoutX- og layoutY-attributtene og utseendet av attributter som stroke, strokeType og fill. Hvis du kopierer FXML-en inn i Eclipse og endrer litt på disse, så ser du fort hva slags effekt de har. Øverst/ytterst har vi en AnchorPane, som gjør det lett å plassere elementer på bestemte koordinater. Navn som Circle og Anchor er egentlig navn på Java-klasser, som er litt lenger. F.eks. heter AnchorPane egentlig javafx.scene.layout.AnchorPane og Circle heter egentlig javafx.scene.shape.Circle. For å slippe å skrive så lange navn, så bruker man <?import ...> øverst i fila.

To viktige deler av FXML-fila er fx:id-attributtet og attributter som begynner med "on", f.eks. onAction-attributtet i Button-elementet.

fx:id-attributt og Java-variabel

Alle delene av skjermbildet som programmet skal kunne forandre på, f.eks. gjøre synlig eller usynlig, endre teksten eller posisjonen til osv. må ha en fx:id. Denne du legge inn med Scene Builder eller FXML-editoren. I FXML-en over er dette brukt til å sette navn på Button-objektet og på Polygon-objektet (som tilsvarer den grå knivaktige tingen i hånda på strekmannen):

<Button fx:id="trykkHerKnapp" ... text="Trykk her!" />
<Polygon fx:id="kniv" .../>

 I Java-koden må du lage en variabel med samme navn som denne fx:id-en, og typen til variablen må tilsvare typen element, f.eks Button for knapp, Polygon for mangekant Text for tekst, Line for strek:

@FXML
Button trykkHerKnapp;
@FXML
Polygon kniv;

Du kan selvfølgelig lage andre variabler også, for å holde rede på alt som trengs for å få spillet til å virke.

Java-metode og onHendelse-attributt

Alt brukeren gjør og som programmet skal reagere på, må gjøres av en hendelsesmetode (samme som funksjon i Python). I FXML-en må du legge inn navnet på denne metoden i det samme elementet som skal trigge metoden og med # foran. Dette eksempel-programmet skal reagere på en knappen, så da må FXML-en se slik ut:

<Button fx:id="trykkHerKnapp" ... onAction="#handleTrykkHer" text="Trykk her!" />

 I Java-koden må metoden se slik ut:

@FXML
void handleTrykkHer() {
	// her legges koden for det som skal skje
}

I koden i hendelsesmetodene så kan en bruke variablene for elementene som har fx:id-attributter, til å endre på skjermbildet, og dermed skape liv i skjermbildet! Hvis kniv er definert som vist over, så kan du f.eks. skrive kniv.setLayoutX(kniv.getLayoutX() - 10) for å flytte kniven litt til venstre og trykkHerKnapp.setText("Du trykket meg!") for å endre på knappe-teksten.

Java-koden

Java-koden er på en måte delt i to deler:

  1. Metodene (funksjonene) main og start sørger for å starte opp programmet og laste inn FXML-innholdet i et vindu. Etter at vinduet er laget og fylt med FXML-innholdet, så settes variablene som er markert med @FXML til objektene som har tilsvarende fx:id (med litt Java-magi).

  2. Når programmet er igang vil hendelsesmetodene bli kalt når spilleren gjør bestemte ting. F.eks. vil handleTrykkHer bli kalt når brukeren trykker på knappen, fordi vi har skrevet onAction="#handleTrykkHer" i Button-elementet. Hvis du lager flere knapper, så må du finne på nye metodenavn og legge dem inn i både Java-koden og FXML-en på samme måte.

Her er koden for eksemplet:

package trinn2;

import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.shape.Polygon;
import javafx.stage.Stage;

public class Strekmann extends Application {
    @Override
    public void start(Stage primaryStage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(this.getClass().getResource("Strekmann.fxml"));
        fxmlLoader.setController(this);
        Parent root = (Parent) fxmlLoader.load();
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
 
    @FXML
    Button trykkHerKnapp;
    @FXML
    Polygon kniv;

    @FXML
    void handleTrykkHer() {
        double layoutX = kniv.getLayoutX() - 10;
        kniv.setLayoutX(layoutX);
        String melding = "Bom!";
        if (layoutX > 50 && layoutX < 80) {
            melding = "Treff!";
        }
        trykkHerKnapp.setText(melding);
    }
}

Det eneste hendelsesmetoden gjør er å

  • flytte kniven til venstre ved å hente ut layoutX, trekke fra 10 og legge den tilbake
  • sjekke om kniven er omtrent i blinken, ved å teste om layoutX er > 50 og < 80
  • endre på teksten i knappen for å gi melding til spilleren om det er bom eller treff

Oppgave

Prøv om du endre på layoutY for blinken, slik at du også trenger en knapp som flytter kniven opp (eller ned)! Husk at du da også må sjekke om layoutY er passende for å finne ut om det ble bom eller treff.

 

  • No labels