Mir hat einer gesagt, dass wenn er bei Javafx auf ein Panel ein Bild oder eine GUI ladet dass das Bild automatisch auf die Größe angepasst wird, wie das Fenster in dem Moment ist, egal ob Vollbild etc, aber wie geht das?
Also wenn ich den Scenebuilder nutze, was meint Anchor auf 0 setzen?
Pane root = new Pane();
Circle kreis1 = new Circle();
kreis1.centerXProperty().bind(root.widthProperty().divide(2));
kreis1.centerYProperty().bind(root.heightProperty().divide(2));
kreis1.radiusProperty().bind(root.widthProperty().divide(4));
root.getChildren().add(kreis1);
Danke, aber wie genau mache ich das? Also wenn ich den Scenebuilder nutze, was meint Anchor auf 0 setzen?Da ist die Frage erst einmal, was Du wie nutzt. Generell kannst Du ein Bild mit einem ImageView darstellen. Wenn Du es auf einer AnchorPane darstellst, dann ist es einfach, weil Du da die Anchor einfach alle auf 0 setzt. Damit füllt die ImageView immer die ganze Pane aus.
Du kannst fitWidth und fitHeight nutzen um dafür zu sorgen, dass das Bild immer in der Größe verändert wird und preserveRatio falls Du sicher gehen willst, dass es nicht verzerrt wird.
Also wenn ich den Scenebuilder nutze, was meint Anchor auf 0 setzen?
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="anchorPane" prefHeight="410.0" prefWidth="485.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.kneitzel.MainWindow">
<children>
<ImageView fx:id="imageView" layoutX="-2.0" layoutY="-1.0" pickOnBounds="true" preserveRatio="true" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
package de.kneitzel;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import java.net.URL;
import java.util.ResourceBundle;
public class MainWindow implements Initializable {
@FXML
private AnchorPane anchorPane;
@FXML
private ImageView imageView;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
Image image = new Image(getClass().getResourceAsStream("/TestBild.png"));
imageView.setImage(image);
imageView.fitWidthProperty().bind(anchorPane.widthProperty());
}
}
package de.kneitzel;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import java.net.URL;
import java.util.ResourceBundle;
public class MainWindow implements Initializable {
@FXML
private AnchorPane anchorPane;
@FXML
private ImageView imageView;
double ratio;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
Image image = new Image(getClass().getResourceAsStream("/TestBild.png"));
imageView.setImage(image);
ratio = image.getWidth() / image.getHeight();
anchorPane.widthProperty().addListener(e -> setSize());
anchorPane.heightProperty().addListener(e -> setSize());
}
public void setSize() {
if (anchorPane.getWidth() / anchorPane.getHeight() < ratio) {
imageView.setFitWidth(0.);
imageView.setFitHeight(anchorPane.getHeight());
} else {
imageView.setFitHeight(0.);
imageView.setFitWidth(anchorPane.getWidth());
}
}
}
Ich habe jetzt den Code teilweise versucht anzuwenden und das klappt auch, nur habe ich das Bild schon zugefügt, weshalb ich das hier nicht gemacht habe.Wenn Du ein Element auf eine AnchotPane setzt, dann kannst Du Anchor Pane Constraints setzen. Damit wird die Größe immer relativ zu der Grenze angepasst. 0 bedeutet halt, dass zwischen der Grenze der AnchorPane hin zu dem Image immer genau 0 Pixel Platz sind.
Anhang anzeigen 20748
Preserve Ratio ist direkt unter Properties zu finden und ist per default an:
Anhang anzeigen 20750
Das wäre die Erläuterung zu dem, was ich da so geschrieben habe. Das ist aber so nicht ganz, was Du genau willst. Die ImageView setzt seine Größe auf diese fitHeight / fitWidth Größe. Daher bringen diese Anchors nicht so viel, wie ich ursprünglich dachte.
Ich habe keine Ahnung, was genau Du machen willst. Aber machen wir ein einfaches Beispiel: Wir machen nur ein einziges Fenster und da packen wir nur eine ImageView rein.
Das kannst Du noch mit dem SceneBuilder machen. Ebenso das Vergeben der fx:id und so. Und man kann oben und unten ein anchor mit Wert 0 setzen, wobei ein Setzenm auf Posiotion 0, 0 auch ausreichen sollte.
Dann brauchst Du einen Controller, den Du auch einträgst im fxml.
Danach ist abe rerst einmal Schluss mit SceneBuilder fürchte ich. Denn die fitHeight / fitWidth Werte müssen noch gelöscht werden. Dann sollte unter dem Strich das FXML so in etwa aussehen:
XML:<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.image.*?> <?import javafx.scene.layout.*?> <AnchorPane fx:id="anchorPane" prefHeight="410.0" prefWidth="485.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.kneitzel.MainWindow"> <children> <ImageView fx:id="imageView" layoutX="-2.0" layoutY="-1.0" pickOnBounds="true" preserveRatio="true" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" /> </children> </AnchorPane>
Die anchorView und imageView wollen wir dann natürlich injecten lassen in den Controller. Dazu brauchen wir zwei Instanzvariablen, die mit @FXML Annotation versehen werden.
Dann implementieren wir noch Initializable und implementieren noch diese Methode.
Dort laden wir erst einmal ein Image und packen es in die ImageView.
Und dann wollen wir die ImageView in der Größe anpassen, wann immer die Breite des Fensters sich ändert. Dazu können wir die Properties verwenden - das wird dann richtig einfach und wir erhalten Code wie:
Java:package de.kneitzel; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; import java.net.URL; import java.util.ResourceBundle; public class MainWindow implements Initializable { @FXML private AnchorPane anchorPane; @FXML private ImageView imageView; @Override public void initialize(URL url, ResourceBundle resourceBundle) { Image image = new Image(getClass().getResourceAsStream("/TestBild.png")); imageView.setImage(image); imageView.fitWidthProperty().bind(anchorPane.widthProperty()); } }
Das Bild muss natürlich als Ressource zur Verfügung stehen - da hatte ich jetzt einfach ein kleines Testbild genommen.
Jetzt hast Du aber ggf. unten eine weiße Fläche, wenn das Fenster zu hoch ist. Das muss natürlich auch nicht sein. Dazu könnten wir einfach auf Veränderungen der AnchorPane bei Breite und Höhe reagieren um dann entweder die Breite oder die Höhe fest zu setzen. Das sähe dann so aus:
Java:package de.kneitzel; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; import java.net.URL; import java.util.ResourceBundle; public class MainWindow implements Initializable { @FXML private AnchorPane anchorPane; @FXML private ImageView imageView; double ratio; @Override public void initialize(URL url, ResourceBundle resourceBundle) { Image image = new Image(getClass().getResourceAsStream("/TestBild.png")); imageView.setImage(image); ratio = image.getWidth() / image.getHeight(); anchorPane.widthProperty().addListener(e -> setSize()); anchorPane.heightProperty().addListener(e -> setSize()); } public void setSize() { if (anchorPane.getWidth() / anchorPane.getHeight() < ratio) { imageView.setFitWidth(0.); imageView.setFitHeight(anchorPane.getHeight()); } else { imageView.setFitHeight(0.); imageView.setFitWidth(anchorPane.getWidth()); } } }
Das wäre die Variante, bei der immer entweder unten oder rechts etwas abgeschnitten wird. Wenn man in der Abfrage aus dem < ein > macht, dann würde man immer unten oder rechts einen weissen Streifen haben.