TL; DR : чтобы сделать привязку в файле F XML, необходимо сделать свойство изображения видимым (например, через ObjectProperty<Image>
).
В F XML нет ничего особенного. Он просто определяет способ описания графа объектов в синтаксисе XML, который интерпретируется FXMLLoader
и преобразуется в обычные Java объекты. Он использует относительно базовые c правила и соглашения Java (FX) Bean для выполнения sh. Дополнительную информацию можно найти в документе Введение в F XML.
Когда вы используете привязки выражений, вы используете API привязки интерфейса JavaFX Property
. Другими словами, когда у вас есть:
<ImageView image="${controller.image}"/>
Это в основном то же самое, что делать следующее в коде:
public class FooController {
private final ObjectProperty<Image> image = new SimpleObjectProperty<>(this, "image");
// property-getter, getter, and setter omitted for brevity
@FXML private ImageView imageView; // corresponding fx:id="imageView" in FXML file
@FXML
private void initialize() {
// the "expression binding"
imageView.imageProperty().bind(imageProperty());
}
}
И вот откуда возникает проблема в вашем примере. Ваш контроллер не предоставляет наблюдаемое свойство изображения; у вас есть только метод getImage()
. Поскольку ничего не наблюдается, ImageView
не может автоматически обновляться при изменении Image
(т. Е. Не к чему привязываться).
Вот пример, где контроллер предоставляет ObjectProperty<Image>
.
App.f xml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.StackPane?>
<BorderPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="Controller" prefWidth="1000" prefHeight="650">
<top>
<Button text="Browse..." onAction="#handleBrowse" BorderPane.alignment="CENTER_RIGHT">
<BorderPane.margin>
<Insets topRightBottomLeft="5"/>
</BorderPane.margin>
</Button>
</top>
<center>
<ScrollPane fitToHeight="true" fitToWidth="true" vbarPolicy="NEVER" hbarPolicy="NEVER"
pannable="true">
<StackPane minWidth="-Infinity" minHeight="-Infinity">
<ImageView image="${controller.image}"/>
</StackPane>
</ScrollPane>
</center>
</BorderPane>
Контроллер. java:
import java.io.File;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Window;
public class Controller {
private final ObjectProperty<Image> image = new SimpleObjectProperty<>(this, "image");
public final void setImage(Image image) { this.image.set(image); }
public final Image getImage() { return image.get(); }
public final ObjectProperty<Image> imageProperty() { return image; }
@FXML
private void handleBrowse(ActionEvent event) {
event.consume();
Window window = ((Button) event.getSource()).getScene().getWindow();
FileChooser chooser = new FileChooser();
chooser
.getExtensionFilters()
.addAll(new ExtensionFilter("Image Files", "*.png", "*.jpg", "*.jpeg", "*.gif"));
File file = chooser.showOpenDialog(window);
if (file != null) {
setImage(new Image(file.toURI().toString()));
}
}
}
Main. java
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 Main extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Parent root = FXMLLoader.load(Main.class.getResource("App.fxml"));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
В качестве отступления, пожалуйста, следуйте Java соглашениям об именах , по крайней мере, при публикации на форуме c. Эти подчеркивания (_
) в именах переменных / полей не являются традиционными, и другим Java программистам становится сложнее понять ваш код.