Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3
Excerpt

Med JavaFX er det lett å lage enkel 2D-grafikk, og med FXML så blir det enda enklere!

 

Figurer i FXML

Med FXML er det nokså enkelt å lage større figurer, som en sammensetning av enkle figur-elementer som sirkler, rektangler og streker. En enkel strekmann kan se ut som følger med FXML:

...

Code Block
languagejavafx
collapsetrue
<?xml version="1.0" encoding="UTF-8"?>
 
<?import javafx.scene.textlayout.TextPane?>
<?import javafx.scene.control.TextFieldGroup?>
<?import javafx.scene.controlshape.ButtonCircle?>
<?import javafx.scene.layoutshape.BorderPaneLine?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.HBox?>

<?import javafx.scene.layout.Region?>
<?import javafx.scene.Group?>
<?import javafx.scene.shape.Circle?>
<?import javafx.scene.shape.Line?>

<Pane xmlns:fx="http://javafx.com/fxml"
     minWidth="400" minHeight="600">
    <Group layoutY="50">
        
<Pane xmlns:fx="http://javafx.com/fxml"
     minWidth="400" minHeight="600">
    <Group layoutY="50">
        <Circle layoutX="100" layoutY="20" radius="20" stroke="black" fill="white"/>
        <Circle layoutX="112" layoutY="20" radius="2" stroke="black" fill="blue"/>
        <Line layoutX="120" layoutY="20" startX="0" startY="-4" endX="3" endY="0" stroke="black"/>
        <Line layoutX="120" layoutY="20" startX="3" startY="0" endX="0" endY="1" stroke="black"/>
        <Line layoutX="100" layoutY="40" endX="0" endY="30" stroke="black"/>
        <Group layoutX="100" layoutY="50" visible="true">
            <Line layoutY="0"  endX="-10" endY="10" stroke="black"/>
            <Line layoutY="0"  endX= "10" endY="10" stroke="black"/>
            <Line layoutY="20" endX="-10" endY="15" stroke="black"/>
            <Line layoutY="20" endX= "10" endY="15" stroke="black"/>
        </Group>
    </Group>
</Pane>

Code Block
languagejava
collapsetrue
package trinn2;

import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

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

Den komplette FXML-koden er vist til venstre. Import-linjene øverst trengs for å kunne bruke navn tilsvarende Java-klasser lenger ned i fila. F.eks. vil Circle egentlig referere til java-klassen javafx.scene.shape.Circle. Java-koden antar her at FXML-fila ligger i samme mappe som java-fila.

...

Code Block
languagejava
    @FXML
    void walk() {
        step = ! step;
        stickMan.setLayoutX(stickMan.getLayoutX() + 5);
        update();
    }

@FXML angir at walk-metoden deltar i håndtering av hendelser vha. FXML-automatikken

 

Code Block
languagejavafx
        <HBox>
            <Button text="Walk!" onAction="#walk"/>
        </HBox> 

onAction="#walk" angir at knappens action-hendelse skal trigge walk-metoden

Her er komplett Java- og FXML-kode:

StickMan2

Teknikken beskrevet over er brukt i en utvidelse av eksemplet over, hvor en strekmann "spaserer" mot høyre og blunker når brukeren klikker på en knapp. Bevegelsen mot høyre håndteres ved å øke x-koordinaten for hvert steg (klikk på knappen), med følgende linje i walk-metoden: stickMan.setLayoutX(stickMan.getLayoutX() + 5); Skritt-effekten håndteres ved å ha to sett med armer og ben og veksle mellom dem ved å slå dem av og på med kall til setVisible-metoden. Blunke-effekten håndteres ved å veksle mellom to farger med kall til setFill-metoden. Steg-logikken er fordelt mellom walk-metoden, som bare lar step-feltet veksle mellom true og false, og update-metoden, som kaller setVisible- og setFill-metodene med verdier avhengig av step-feltet.

Code Block
    void update() {
        if (step) {
            eye.setFill(Color.BLUE);
        } else {
            eye.setFill(Color.WHITE);
        }
        armsAndLegs1.setVisible(step);
        armsAndLegs2.setVisible(! step);
    }

Her er komplett Java- og FXML-kode:

Code Block
languagejava
collapsetrue
package trinn2;

import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;

public class StickMan2 extends Application {
    @Override
    public void start(Stage primaryStage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader();
        fxmlLoader.setController(this);
        Parent root = (Parent) fxmlLoader.load(this.getClass().getResourceAsStream("StickMan2.fxml"));
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
    @FXML Node stickMan, armsAndLegs1, armsAndLegs2;
    @FXML Shape eye;
    
    boolean step = true;
    @FXML
    void initialize() {
        update();
    }
    void update() {
        if (step) {
            eye.setFill(Color.BLUE);
        } else {
            eye.setFill(Color.WHITE);
        }
        armsAndLegs1.setVisible(step);
        armsAndLegs2.setVisible(! step);
    }
    @FXML
    void walk() {
        step = ! step;
        stickMan.setLayoutX(stickMan.getLayoutX() + 5);
        update();
    }
    public static void main(String[] args) {
        launch(args);
    }
}
Code Block
languagejavafx
collapsetrue
<?xml version="1.0" encoding="UTF-8"?>
 
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.Pane?>

<?import javafx.scene.Group?>
<?import javafx.scene.shape.Circle?>
<?import javafx.scene.shape.Line?>

<BorderPane xmlns:fx="http://javafx.com/fxml"
     minWidth="400">
    <top>
        <Button text="Walk!" onAction="#walk"/>
    </top>
    <center>
        <Pane minWidth="400" minHeight="600">
            <Group fx:id="stickMan">
                <Circle layoutX="100" layoutY="20" radius="20" stroke="black" fill="white"/>
                <Circle fx:id="eye" layoutX="112" layoutY="20" radius="2" stroke="black" fill="blue"/>
                <Line layoutX="120" layoutY="20" startX="0" startY="-4" endX="3" endY="0" stroke="black"/>
                <Line layoutX="120" layoutY="20" startX="3" startY="0" endX="0" endY="1" stroke="black"/>
                <Line layoutX="100" layoutY="40" endX="0" endY="30" stroke="black"/>
                <Group fx:id="armsAndLegs1" layoutX="100" layoutY="50" visible="true">
                    <Line layoutY="0"  endX= "-5" endY="10" stroke="black"/>
                    <Line layoutY="0"  endX= "10" endY="10" stroke="black"/>
                    <Line layoutY="20" endX="-10" endY="15" stroke="black"/>
                    <Line layoutY="20" endX=  "5" endY="15" stroke="black"/>
                </Group>
                <Group fx:id="armsAndLegs2" layoutX="100" layoutY="50" visible="false">
                    <Line layoutY="0"  endX="-10" endY="10" stroke="black"/>
                    <Line layoutY="0"  endX=  "5" endY="10" stroke="black"/>
                    <Line layoutY="20" endX= "-5" endY="15" stroke="black"/>
                    <Line layoutY="20" endX= "10" endY="15" stroke="black"/>
                </Group>
            </Group>
        </Pane>
    </center>
</BorderPane>

StickMan3

Dette er en annen variant som bruker de samme teknikkene, og lar brukeren bruke piltastene for å flytte strekmannen. Her er komplett Java- og FXML-kode:

Code Block
languagejava
collapsetrue
package trinn2;

import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;

public class StickMan3 extends Application {
    @Override
    public void start(Stage primaryStage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader();
        fxmlLoader.setController(this);
        Parent root = (Parent) fxmlLoader.load(this.getClass().getResourceAsStream("StickMan3.fxml"));
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
    @FXML Pane stickManPane;
    @FXML Node stickMan, armsAndLegs1, armsAndLegs2;
    @FXML Shape leftEye, rightEye;
    
    boolean step = true;
    KeyCode direction = KeyCode.DOWN;
    
    @FXML
    void initialize() {
        update();
    }
    void update() 
Code Block
languagejava
collapsetrue
package trinn2;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
public class StickMan2 extends Application {
    @Override
    public void start(Stage primaryStage) throws IOException {
        FXMLLoaderif fxmlLoader(direction == new FXMLLoader();
KeyCode.LEFT) {
            fxmlLoaderleftEye.setControllersetVisible(thistrue);
        Parent root = (Parent) fxmlLoaderrightEye.load(this.getClass().getResourceAsStream("StickMan2.fxml")setVisible(false);
        } else if primaryStage.setScene(new Scene(root));
(direction == KeyCode.RIGHT) {
         primaryStage.show(   leftEye.setVisible(false);
     }
    @FXML Node stickMan, armsAndLegs1, armsAndLegs2;
 rightEye.setVisible(true);
        @FXML} Shapeelse eye;{
    
     boolean step = leftEye.setVisible(true);
       @FXML
    void initializerightEye.setVisible(true) {;
        update();}
    }
    voidif update(step) {
           if (step) {leftEye.setFill(Color.BLUE);
            eyerightEye.setFill(Color.BLUE);
);
        } else {
          } else { leftEye.setFill(Color.WHITE);
            eyerightEye.setFill(Color.WHITE);
        }
        armsAndLegs1.setVisible(step);
        armsAndLegs2.setVisible(! step);        
    }
    
    @FXML
    void walk( keyPressed(KeyEvent keyEvent) {
        step = ! step;
        if (keyEvent.getCode() == KeyCode.LEFT) {
        step = ! step;
        stickMan.setLayoutX(stickMan.getLayoutX() +- 5);
        }  update();else if (keyEvent.getCode() == KeyCode.RIGHT) {
    }
     public static void main(String[] args) {
 stickMan.setLayoutX(stickMan.getLayoutX() + 5);
         launch(args);
    }
}
Code Block
languagejavafx
collapsetrue
<?xml version="1.0" encoding="UTF-8"?>
 
<?import javafx.scene.text.Text?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.HBox?>

<?import javafx.scene.layout.Region?>
<?import javafx.scene.Group?>
<?import javafx.scene.shape.Circle?>
<?import javafx.scene.shape.Line?>

<BorderPane xmlns:fx="http://javafx.com/fxml"
     minWidth="400">
    <top>
        <HBox>
} else if (keyEvent.getCode() == KeyCode.DOWN) {
            stickMan.setLayoutY(stickMan.getLayoutY() + 5);
        } else if (keyEvent.getCode() == KeyCode.UP) {
            stickMan.setLayoutY(stickMan.getLayoutY() - 5);
        } else {
            return;
        }
        direction = keyEvent.getCode();
        update();
    }
    public static void main(String[] args) {
        launch(args);
    }
}
Code Block
languagejavafx
collapsetrue
<?xml version="1.0" encoding="UTF-8"?>
 
<?import javafx.scene.layout.Pane?>

<?import javafx.scene.Group?>
<?import javafx.scene.shape.Circle?>
<?import javafx.scene.shape.Line?>

<Pane xmlns:fx="http://javafx.com/fxml" minWidth="400 <Button text="Walk!" onAction="#walk"/>
        </HBox>
    </top>
    <center>
        <Pane minWidth="400" minHeight="600">
            <Group<Pane fx:id="stickManstickManPane">
                <Circle layoutX="100" layoutY="20" radius="20" stroke="black" fill="white"/ minWidth="400" minHeight="600" focusTraversable="true" onKeyPressed="#keyPressed">
        <Group fx:id="stickMan">
       <Circle fx:id="eye"     <Circle layoutX="112100" layoutY="20" radius="220" stroke="black" fill="bluewhite"/>
                <Line<Circle fx:id="leftEye" layoutX="12092" layoutY="20" startXradius="02" startYstroke="-4black" endXfill="3" endY="0" stroke="black"blue"/>
            <Circle    <Line fx:id="rightEye" layoutX="120110" layoutY="20" startXradius="3" startY="0" endX="02" endYstroke="1black" strokefill="blackblue"/>
                <Line layoutX="100" layoutY="40" endX="0" endY="30" stroke="black"/>
                <Group fx:id="armsAndLegs1" layoutX="100" layoutY="50" visible="true">
                    <Line layoutY="0"  endX= "-5" endY="10" stroke="black"/>
                    <Line layoutY="0"  endX= "10" endY="10" stroke="black"/>
                    <Line layoutY="20" endX="-10" endY="15" stroke="black"/>
                    <Line layoutY="20" endX=  "5" endY="15" stroke="black"/>
                </Group>
                <Group fx:id="armsAndLegs2" layoutX="100" layoutY="50" visible="false">
                    <Line layoutY="0"  endX="-10" endY="10" stroke="black"/>
                    <Line layoutY="0"  endX=  "5" endY="10" stroke="black"/>
                    <Line layoutY="20" endX= "-5" endY="15" stroke="black"/>
                    <Line layoutY="20" endX= "10" endY="15" stroke="black"/>
                </Group>
            </Group>
        </Pane>
    </center>
</BorderPane>
Pane>