Я хочу установить значения H и V на Scrollpane, но после изменения внутреннего содержимого.
Некоторый контекст - Я получил следующую структуру:
![enter image description here](https://i.stack.imgur.com/o0IyJ.png)
Я прикрепил событие .setOnScroll(...)
(мышь) к StackPane, и когда это происходит, внутреннее содержимое изменяется (изображение) до некоторых значений (также называемое масштабирование). Я хочу добавить, что минимальный размер StackPane привязан к размеру окна прокрутки, а размер панели - к размеру изображения, чтобы все работало правильно.
До этого момента все работало нормально, когда содержимое изменяет размер, полосы прокрутки обновляются, и все корректируется, как и должно быть, но я хочу сохранить или, вернее, установить позиции полос прокрутки для некоторых значений, чтобы продолжать масштабирование до предыдущей средней точки (что-то вроде увеличить фотошоп). В этом случае я добавил эту строку в свой обратный вызов, чтобы проверить это:
scrollPane.setHvalue(0.5);
Сама функция работает, но она перезаписывается позже (возможно, при повторном вычислении компоновки), и поэтому всегда неверна. Я проверил значения через событие
scrollPane.hvalueProperty().addListener((observable, oldvalue, newvalue) -> {
System.out.println(newvalue);
});
и на выходе получается вид
0.5
0.45172283226050736
0.5
0.45196805476326296
0.5
0.4522703818369453
// or this when scaled down
0.5
0.5591296121097445
0.5
0.5608324439701174
Вот почему я пришел к выводу, что мне удалось установить 0.5
, но более поздняя разметка, вероятно, установила другое значение для измененного размера контента, потому что я изменил ограничения размера на Pane
и StackPane
.
Тогда мой вопрос Как мне это сделать?
Есть ли какое-либо событие onResize для коррекции или форсирования моего собственного значения? или другой способ запланировать событие прокрутки или мои обновления, которые будут сделаны при пересчете макета?
// РЕДАКТИРОВАТЬ
Я очистил код и вот пример:
Main.java
package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXMLLoader;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("Sample.fxml"));
Scene scene = new Scene(root,800,600);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
application.css пусто
/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */
Sample.fxml (заменить URL-адрес изображения)
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.StackPane?>
<BorderPane xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.SampleController">
<center>
<ScrollPane fx:id="scrollPane" prefHeight="600.0" prefWidth="800.0" BorderPane.alignment="CENTER">
<content>
<StackPane fx:id="stackPane">
<children>
<Pane fx:id="clipContainer">
<children>
<ImageView fx:id="img" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../../../Desktop/sample.jpg" />
</image>
</ImageView>
</children>
</Pane>
</children>
</StackPane>
</content>
</ScrollPane>
</center>
</BorderPane>
и SampleController.java
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
public class SampleController implements Initializable {
@FXML
private Pane clipContainer;
@FXML
private StackPane stackPane;
@FXML
private ImageView img;
@FXML
private ScrollPane scrollPane;
final double SCALE_DELTA = 1.1;
private double imgW;
private double imgH;
private double scale = 1;
@Override
public void initialize(URL location, ResourceBundle resources) {
clipContainer.setStyle("-fx-background-color: #999999");
stackPane.setStyle("-fx-background-color: #CCCCCC");
imgW = img.getImage().getWidth();
imgH = img.getImage().getHeight();
// bind max and min to adjust to new image bounds
stackPane.minWidthProperty().bind(Bindings.createDoubleBinding(() ->
scrollPane.getViewportBounds().getWidth(), scrollPane.viewportBoundsProperty()
));
stackPane.minHeightProperty().bind(Bindings.createDoubleBinding(() ->
scrollPane.getViewportBounds().getHeight(), scrollPane.viewportBoundsProperty()
));
clipContainer.maxWidthProperty().bind(Bindings.createDoubleBinding(() ->
img.getFitWidth(), img.fitWidthProperty()
));
clipContainer.maxHeightProperty().bind(Bindings.createDoubleBinding(() ->
img.getFitHeight(), img.fitHeightProperty()
));
// initial scale
img.setFitWidth(imgW * 1);
img.setFitHeight(imgH * 1);
// on mouse scroll
stackPane.setOnScroll(event -> {
event.consume();
if (event.getDeltaY() == 0) {
return;
}
double scaleFactor =
(event.getDeltaY() > 0)
? SCALE_DELTA
: 1/SCALE_DELTA;
scale *= scaleFactor;
img.setFitWidth(imgW * scale);
img.setFitHeight(imgH * scale);
// HERE i want to do something to keep my image where it was
scrollPane.setHvalue(0.5);
});
scrollPane.hvalueProperty().addListener((observable, oldvalue, newvalue) -> {
System.out.println(newvalue);
});
}
}