Reputation: 51
I am trying to re-size an image so it fits (scaled) in the space allotted by a SplitPane
(for workaround suggestions: this image will change when running the program, it should be generated from the text). The ImageView I'm using currently changes the location of the SplitPane
Divider
. The divider can never cause the ImageView
to decrease past the size of the image.
Two images showing this behavior.
Linking the ImageView
fitWidthProperty to a VBox
has not given me the resize behavior I expected. Increasing the ImageView
's size does work (where it is fixed without the binding), but the image never grows, it just gets borders around it.
My MWE:
sample.fxml
:
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<SplitPane orientation="HORIZONTAL" xmlns:fx="http://javafx.com/fxml">
<TextArea fx:id="textArea"/>
<VBox fx:id="vBox" alignment="CENTER">
<HBox fx:id="hBox" alignment="CENTER">
<ImageView fx:id="imageView"/>
</HBox>
</VBox>
</SplitPane>
Controller.java
:
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
public class Controller {
@FXML
private TextArea textArea = new TextArea();
@FXML
private VBox vBox = new VBox();
@FXML
private HBox hBox = new HBox();
@FXML
private ImageView imageView = new ImageView();
public Controller() {
imageView.fitWidthProperty().bind(vBox.widthProperty());
imageView.fitHeightProperty().bind(hBox.heightProperty());
}
public void start() {
textArea.setText("text");
Image image = new Image("https://www.google.nl/images/srpr/logo11w.png");
imageView.setImage(image);
}
}
and Main.java
:
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(final Stage primaryStage) throws Exception {
final Controller controller = new Controller();
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("sample.fxml"));
fxmlLoader.setController(controller);
final Parent root = fxmlLoader.load();
primaryStage.setTitle("MWE");
final Scene scene = new Scene(root, 640, 480);
primaryStage.setScene(scene);
primaryStage.show();
controller.start();
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 5
Views: 3317
Reputation: 366
The problem is that by the SplitPane documentation
Dividers moving to the left/top will stop when the node's min size is reached.
And for some reason a SplitPane specifically uses the minHeight(double) and minWidth(double) functions of its children to get those values (not the min settings by themselves). So my take on this is to create an ImageView with those functions overridden
ImageView imageView = new ImageView() {
@Override public double minHeight(double width) { return 80; }; //some hard stop value
@Override public double minWidth(double height) { return 80; };
};
Then put that ImageView into a StackPane, that one into the SplitPane, then bind the fitWidth and fitHeight properties
SplitPane...
StackPane imagePane = new StackPane(imageView);
splitPane.getItems().add(imagePane);
imageView.fitWidthProperty().bind(imagePane.widthProperty());
imageView.fitHeightProperty().bind(imagePane.heightProperty());
imageView.setPreserveRatio(true);
Upvotes: 0
Reputation: 11
this is my sample for you!
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<StackPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center">
<SplitPane fx:id="splitpane">
<VBox fx:id="left" prefWidth="300" prefHeight="200" style="-fx-background-color: antiquewhite">
<ImageView fx:id="image1" preserveRatio="true" pickOnBounds="true">
<image>
<Image url="@/sample/test.jpg"/>
</image>
</ImageView>
</VBox>
<VBox fx:id="right" prefWidth="300" prefHeight="300" style="-fx-background-color: aquamarine">
<ImageView fx:id="image2" preserveRatio="true" pickOnBounds="true">
<image>
<Image url="@/sample/test.jpg"/>
</image>
</ImageView>
</VBox>
</SplitPane>
package sample;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.SplitPane;
import javafx.scene.image.ImageView;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable {
@FXML
ImageView image1;
@FXML
ImageView image2;
@FXML
SplitPane splitpane;
@Override
public void initialize(URL location, ResourceBundle resources) {
splitpane.getDividers().get(0).positionProperty().addListener((observable, oldValue, newValue) -> {
System.out.println(newValue);
int w = 600;
double w1 = w * newValue.doubleValue();
double w2 = w - w1;
image1.setFitWidth(w1);
image2.setFitWidth(w2);
});
}
}
Upvotes: 1
Reputation: 36792
You can try binding the ImageView's fitWidthProperty()
to the SplitPane's divider position property.
A binding similar to this should work :
imageView.fitWidthProperty().bind(Bindings.subtract(1,
splitPane.getDividers().get(0).positionProperty())
.multiply(splitPane.widthProperty());
Upvotes: 2