Bilder in JavaFX einbinden


#1

Im Wiki gibt es einen großen Artikel, der sich mit dem Einbinden von Bildern in Java-Programmen beschäftigt.
Was dort noch fehlt, ist die Vorgehensweise bzw. Beispiel-Code für JavaFX.

Könnte sich das mal jemand anschauen und ergänzen?

Der Artikel wurde nun auch im Wiki eingebaut. Danke an alle Beteiligten.


#2

Würde das gerne machen, aber bei JavaFX lädt man Bilder auf die selbe Art und weiße wie für Swing über ImageIO oder wie auch immer es einem Beliebt.
Eine eigene Bild oder Ladeklasse gibt es nicht für FX.

Zum Anzeigen verwendet man halt die ImageView Klasse. Ist halt nichts anderes wie ein Panel mit einer setImage() Methode.
Aber der Artikel beschäftigt sich ja mit dem “Laden” von Bildern.

Über die FXML kann man glaube ich noch ein Bild einbinden, aber das macht man dann ja direkt im FX WYSIWYG Editor also eigentlich auch nichts erwähnenswertes.

Aber vielleicht will ja wer die obigen Informationen dort hineinschreiben. Habe zurzeit nur ein Mini Smartphone und “mit Glück”-E-Mobilnetzwerk


#3

[quote=TMII]Würde das gerne machen, aber bei JavaFX lädt man Bilder auf die selbe Art und weiße wie für Swing über ImageIO oder wie auch immer es einem Beliebt.
Eine eigene Bild oder Ladeklasse gibt es nicht für FX.[/quote]

Wirklich? Was ist mit

Image (JavaFX 8)

The Image class represents graphical images and is used for loading images from a specified URL.


#4

Ha tatsächlich. Du hast recht, ist mir garnicht aufgefallen o.O
Ich hab einfach die Image Klasse verwendet und Autoimport hat wohl den Rest gemacht oder normale Images funktionieren auch… ich kram nacher gleich mal meinen alten Code raus. Mir ist aber absolut keine Veränderung aufgefallen.

*** Edit ***

Tatsache, der hat die JavaFX Klasse importiert. Die ist natürlich nur in der Model Klasse definiert.
Gut zu wissen.


#5

Hier mal ein einfaches Beispiel entsprechend dem Swing Beispiel PicturePanel, PictureFrame.

Bin für Verbesserungsvorschläge offen und würde noch eine Variante mit FXML nachlegen, sofern gewünscht.


import java.io.PrintWriter;
import java.io.StringWriter;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundImage;
import javafx.scene.layout.BackgroundPosition;
import javafx.scene.layout.BackgroundRepeat;
import javafx.scene.layout.BackgroundSize;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Picture extends Application {

    @Override
    public void start(Stage primaryStage) {

        try {
            Image imgBackground = new Image(getClass().getResource("images/background.jpg").toExternalForm());
            BackgroundImage backgroundImage = new BackgroundImage(
                    imgBackground,
                    BackgroundRepeat.NO_REPEAT,
                    BackgroundRepeat.NO_REPEAT,
                    BackgroundPosition.DEFAULT,
                    BackgroundSize.DEFAULT);
            Background background = new Background(backgroundImage);

            Image imgIcon = new Image(getClass().getResource("icons/icon.png").toExternalForm());
            ImageView imgView = new ImageView(imgIcon);

            Button btn = new Button("Button mit Icon", imgView);
            btn.setText("Button mit Icon");

            StackPane root = new StackPane();
            root.getChildren().add(btn);
            root.setBackground(background);

            Scene scene = new Scene(root, 300, 250);

            primaryStage.setTitle("Bildbetrachter FX");
            primaryStage.setScene(scene);
            primaryStage.show();

        } catch (Exception e) {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("Fehler");

            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);

            alert.setContentText(sw.toString());

            alert.showAndWait();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }

}```

#6

Hier ein Beispiel zum Laden und Anzeigen von Bildern via FXML und CSS.


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

public class PictureApp extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("picture.fxml"));

        Scene scene = new Scene(root);

        scene.getStylesheets().add(getClass().getResource("picture.css").toExternalForm());

        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}```

```package picture;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;

public class PictureController {

    @FXML
    private void handleButtonAction(ActionEvent event) {
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setTitle("Dialog");
        alert.setContentText("You just clicked the Button");

        alert.showAndWait();
    }

}```

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

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

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="picture.PictureController">
    <children>
        <Button fx:id="button" layoutX="10" layoutY="10" onAction="#handleButtonAction" text="Button with Icon" />        
    </children>
</AnchorPane>
[/XML]


#AnchorPane {
-fx-background-image: url(images/background.jpg);
-fx-background-repeat: no-repeat;
-fx-background-position: center center;
}

#button {
-fx-graphic: url(icons/icon.png);
}



Der Code um Hintergrundbild und Bild des Buttons zu setzen befindet sich lediglich in der CSS Datei, die für das Styling verantwortlich ist. Ohne CSS bleibt lediglich Anwendungscode übrig, der einen einfachen Button mit Text auf einem hellen Hintergrund zeichnet.

Die Kombination aus FXML und CSS ist auch mein preferierter Weg um JavaFX-Anwendungen zu erstellen.

#7

@L-ectron-X und “NochUnreg”: Mit ein bißchen erklärendem Text könnte das ja ins Wiki…


#8

Die Änderungen zum Laden von Bildern in JavaFX gegenüber Swing bestehen in den Folgenden Punkten:

  1. Es wird nun die Klasse javafx.scene.image.Image im Gegensatz zu java.awt.Image verwendet.
  2. Die Image-Klasse besitzt nun verschiedene Konstruktoren, die im wesentlichen die Aufgaben der Read-Funktionen aus ImageIO ersetzen, um Bilder aus verschiedenen Quellen zu laden.

In JavaFX gibt es mehrere Möglichkeiten Bilder zu verwenden.

Bilder als Hintergrund
Bilder können als Hintergrund eines Elements verwendet werden.

Das vorgehen hierbei ist wie folgt.

  1. Bild laden
    Image imgBackground = new Image(getClass().getResource("images/background.jpg").toExternalForm());

  2. Bild in ein Hintergrundbild umwandeln

                  imgBackground,
                  BackgroundRepeat.NO_REPEAT,
                  BackgroundRepeat.NO_REPEAT,
                  BackgroundPosition.DEFAULT,
                  BackgroundSize.DEFAULT); ```

3. Hintergrund erstellen
```Background background = new Background(backgroundImage); ```

4. Bei der Komponente (hier root) den neuen Hintergrund setzen
```root.setBackground(background); ```

**Bilder direkt verwenden**
Um Bilder direkt zu verwenden gibt es zudem die Klasse ImageView, diese ist weitestgehend das Pendant zur Klasse ImageIcon.

1. Bild laden
```Image imgIcon = new Image(getClass().getResource("icons/icon.png").toExternalForm());```

2. ImageView mit Bild erstellen
```ImageView imgView = new ImageView(imgIcon);```

  oder direkt

```ImageView imgView = new ImageView(getClass().getResource("icons/icon.png").toExternalForm());```

3. ImageView dem Scene-Graph hinzufügen
```root.getChildren().add(imgView);```

  oder z.B. einem Button das Bild in Form eines Icons hinzufügen.

```Button button = new Button("Button mit Bild", imgView);```

**[U]FXML und CSS[/U]**

Mit JavaFX gibt es zudem die Möglichkeit FXML und CSS einzusetzen.
Hierbei kann die Oberfläche in XML definiert werden und das Aussehen mit CSS beeinflusst werden, so daß eine saubere Trennung der Zuständigkeiten möglich ist.

Eine Oberfläche mit einem Button kann mit FXML wie folgt in der Datei picture.fxml definiert werden

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

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

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="picture.PictureController">
  <children>
      <Button fx:id="button" layoutX="10" layoutY="10" onAction="#handleButtonAction" text="Button with Icon" />        
  </children>
</AnchorPane>[/XML]

In dieser Datei ist noch nichts bezüglich der Bilder zu finden. Um nun Bilder den einzelnen Elementen zuzuweisen wird eine datei pictures.css die so aussieht verwendet.


```html
#AnchorPane {
  -fx-background-image: url(images/background.jpg);
  -fx-background-repeat: no-repeat; 
  -fx-background-position: center center;
}

#button {
  -fx-graphic: url(icons/icon.png);
}

Um die Verknüpfung zwischen FXML und CSS zu bekommen haben die Elemente in der FXML Datei jeweils eine ID.
(id=“AnchorPane”, sowie fx:id=“button”)

In der CSS Datei werden diese Elemente mit dem Selektor #AnchorPane und #button herausgesucht um dort das Aussehen und die Bilder zu setzen.

Um FXML- und CSS-Datei in einer Anwendung zu verbinden kann man wie folgt vorgehen.

  1. View aus der FXML-Datei laden
    Parent root = FXMLLoader.load(getClass().getResource("picture.fxml"));

  2. Scene erstellen und View via Konstruktor zuweisen.
    Scene scene = new Scene(root);

  3. CSS-Stylesheet laden und der Scene hinzufügen.
    scene.getStylesheets().add(getClass().getResource("picture.css").toExternalForm());

  4. Anzeigen der Scene

  stage.show(); ```



Darunter würde ich dann die beiden kompletten Beispiele hinzufügen.

#9

@Unregistered <- Tja, das funktioniert halt nicht :wink: : Möchtest du, dass das so eingefügt wird, oder magst du dich nicht doch registrieren? (Ja, ich weiß, es gibt keinen Ansporn. Sowas wie “Wenn du dich registrierst, verschwinden die lästigen Werbe-Banner, die normalerweise hier im Forum überall eingeblendet werden” funktioniert ja nicht ;-))


#10

@Marco13 ich hab mich mal registriert, nachdem ich jetzt schon mehrfach darum gebeten wurde :wink:

Ich sehe ein Wiki, oder besser jedes Wiki, als einen fortlaufenden Prozess der stetigen Verbesserung und Veränderung an.
Das bisher geschriebene sehe ich als einen Entwurf oder Provisorium an, dass gerne seinen Dienst verrichten kann, bis es durch etwas besseres ersetzt wird.
Wenn es für euch liebe Leute aus der Byte-Welt gut genug ist, dann tut es ins Wiki rein.
Wenn ihr Verbesserungsvorschläge habt, dann lasst diese miteinfließen. Ich bin der erste der daraus einen Profit zieht.


#11

@Marco13 ich hab mich mal registriert, nachdem ich jetzt schon mehrfach darum gebeten wurde :wink:

Ich sehe ein Wiki, oder besser jedes Wiki, als einen fortlaufenden Prozess der stetigen Verbesserung und Veränderung an.
Das bisher geschriebene sehe ich als einen Entwurf oder Provisorium an, dass gerne seinen Dienst verrichten kann, bis es durch etwas besseres ersetzt wird.
Wenn es für euch liebe Leute aus der Byte-Welt gut genug ist, dann tut es ins Wiki rein.
Wenn ihr Verbesserungsvorschläge habt, dann lasst diese miteinfließen. Ich bin der erste der daraus einen Profit zieht.


#12

@ionutbaiu Der erste registrierte Post, und der blieb dann gleich als “Moderated Post” in der Review Queue hängen :wink: (Während Gäste munter drauflosposten können… das Spamschutz-Plugin läuft manchmal Amok - das ist schon unter Beobachtung)

Ich kann das geschriebene aus fachlicher Sicht nicht fundiert beurteilen - aber das ist genau der Punkt: Ich würde darauf zurückgreifen, wenn ich in JavaFX Bilder einbinden müßte :wink: Deswegen denke ich schon, dass es ins Wiki könnte, und wenn es noch etwas zu verbessern gibt, kann das jeder tun.

[allgemeine Anmerkung SlaterB ohne eigenes Posting: vorherige anonyme Postings zugeordnet]