JavaFX setFitHeight()/setFitWidth() 对于在 scrollPane 中使用的图像禁用平移
JavaFX setFitHeight()/setFitWidth() for an image used within a scrollPane disables panning
所以我在 JavaFX 中创建了一个地图,我希望有时可以看到整个地图。但是,问题是,在我将 imageView 设置为适合屏幕尺寸然后将其添加到 scrollPane 之后,我的缩放功能工作正常,但是一旦我放大,我就不允许在图像周围平移。下面是我写的代码。
package gameaspects;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class SourceCodeVersion8 extends Application{
final double SCALE_DELTA = 1.1;
public double SCALE_TOTAL = 1;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
AnchorPane mapAnchorO = addMapAnchor();
Scene mapScene = new Scene(mapAnchorO);
primaryStage.setScene(mapScene);
primaryStage.setFullScreen(true);
primaryStage.setResizable(false);
primaryStage.show();
}
//Creates an AnchorPane for the map
private AnchorPane addMapAnchor()
{
AnchorPane mapAnchor = new AnchorPane();
ScrollPane mapScrollO = addMapScroll();
mapAnchor.getChildren().add(mapScrollO);
AnchorPane.setLeftAnchor(mapScrollO, 0.0);
AnchorPane.setTopAnchor(mapScrollO, 0.0);
AnchorPane.setBottomAnchor(mapScrollO, 0.0);
AnchorPane.setRightAnchor(mapScrollO, 0.0);
return mapAnchor;
}
//Creates an ImageView for the map
private ImageView addMapView()
{
Image mapImage = new Image("WorldProvincialMap-v1.01.png");
ImageView mapView = new ImageView(mapImage);
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
int width = gd.getDisplayMode().getWidth();
int height = gd.getDisplayMode().getHeight();
mapView.setFitHeight(height);
mapView.setFitWidth(width);
return mapView;
}
//Creates a scrollPane for the map
private ScrollPane addMapScroll()
{
ScrollPane mapScroll = new ScrollPane();
ImageView mapViewO = addMapView();
mapScroll.setContent(mapViewO);
mapScroll.setPannable(true);
mapScroll.setVbarPolicy(ScrollBarPolicy.NEVER);
mapScroll.setHbarPolicy(ScrollBarPolicy.NEVER);
mapScroll.addEventFilter(ScrollEvent.ANY, e ->{
e.consume();
if(e.getDeltaY() == 0)
{
return;
}
double scaleFactor =
(e.getDeltaY() > 0)
? SCALE_DELTA
: 1/SCALE_DELTA;
if(scaleFactor * SCALE_TOTAL >= 1)
{
mapScroll.setScaleX(mapScroll.getScaleX() * scaleFactor);
mapScroll.setScaleY(mapScroll.getScaleY() * scaleFactor);
SCALE_TOTAL *= scaleFactor;
}
});
return mapScroll;
}
}
我用 mouseDragHandler 改进了你的版本。
这应该是解决您问题的正确方法!
package test;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class test extends Application {
final double SCALE_DELTA = 1.1;
public double SCALE_TOTAL = 1;
public double dragDeltay;
public double dragDeltax;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
AnchorPane mapAnchorO = addMapAnchor();
Scene mapScene = new Scene(mapAnchorO);
primaryStage.setScene(mapScene);
primaryStage.setFullScreen(true);
primaryStage.setResizable(false);
primaryStage.show();
}
// Creates an AnchorPane for the map
private AnchorPane addMapAnchor() {
AnchorPane mapAnchor = new AnchorPane();
ScrollPane mapScrollO = addMapScroll();
mapAnchor.getChildren().add(mapScrollO);
AnchorPane.setLeftAnchor(mapScrollO, 0.0);
AnchorPane.setTopAnchor(mapScrollO, 0.0);
AnchorPane.setBottomAnchor(mapScrollO, 0.0);
AnchorPane.setRightAnchor(mapScrollO, 0.0);
return mapAnchor;
}
// Creates an ImageView for the map
private ImageView addMapView() {
Image mapImage = new Image("WorldProvincialMap-v1.01.png");
ImageView mapView = new ImageView(mapImage);
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
int width = gd.getDisplayMode().getWidth();
int height = gd.getDisplayMode().getHeight();
mapView.setFitHeight(height);
mapView.setFitWidth(width);
return mapView;
}
// Creates a scrollPane for the map
private ScrollPane addMapScroll() {
ScrollPane mapScroll = new ScrollPane();
ImageView mapViewO = addMapView();
mapScroll.setContent(mapViewO);
mapViewO.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
dragDeltax = mapViewO.getX() - mouseEvent.getScreenX();
dragDeltay = mapViewO.getY() - mouseEvent.getScreenY();
}
});
mapViewO.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
mapScroll.setTranslateX(mouseEvent.getScreenX() + dragDeltax);
mapScroll.setTranslateY(mouseEvent.getScreenY() + dragDeltay);
}
});
mapScroll.setVbarPolicy(ScrollBarPolicy.NEVER);
mapScroll.setHbarPolicy(ScrollBarPolicy.NEVER);
mapScroll.addEventFilter(ScrollEvent.ANY, e -> {
e.consume();
if (e.getDeltaY() == 0) {
return;
}
double scaleFactor = (e.getDeltaY() > 0) ? SCALE_DELTA : 1 / SCALE_DELTA;
if (scaleFactor * SCALE_TOTAL >= 1) {
mapScroll.setScaleX(mapScroll.getScaleX() * scaleFactor);
mapScroll.setScaleY(mapScroll.getScaleY() * scaleFactor);
SCALE_TOTAL *= scaleFactor;
}
});
return mapScroll;
}
}
您正在缩放 ScrollPane
而不是内容。此外,即使您缩放 ImageView
,scaleX
和 scaleY
在计算内容大小时也不会被考虑在内。因此 ImageView
也应该包裹在 Group
:
private ScrollPane addMapScroll() {
ScrollPane mapScroll = new ScrollPane();
ImageView mapViewO = addMapView();
mapScroll.setContent(new Group(mapViewO));
mapScroll.setPannable(true);
mapScroll.setVbarPolicy(ScrollBarPolicy.NEVER);
mapScroll.setHbarPolicy(ScrollBarPolicy.NEVER);
mapScroll.addEventFilter(ScrollEvent.ANY, e -> {
e.consume();
if (e.getDeltaY() == 0) {
return;
}
double scaleFactor
= (e.getDeltaY() > 0)
? SCALE_DELTA
: 1 / SCALE_DELTA;
if (scaleFactor * SCALE_TOTAL >= 1) {
mapViewO.setScaleX(mapViewO.getScaleX() * scaleFactor);
mapViewO.setScaleY(mapViewO.getScaleY() * scaleFactor);
SCALE_TOTAL *= scaleFactor;
}
});
return mapScroll;
}
要"keep the center centered",您需要相应地调整滚动位置:
if (scaleFactor * SCALE_TOTAL >= 1) {
Bounds viewPort = mapScroll.getViewportBounds();
Bounds contentSize = mapViewO.getBoundsInParent();
double centerPosX = (contentSize.getWidth() - viewPort.getWidth()) * mapScroll.getHvalue() + viewPort.getWidth() / 2;
double centerPosY = (contentSize.getHeight() - viewPort.getHeight()) * mapScroll.getVvalue() + viewPort.getHeight() / 2;
mapViewO.setScaleX(mapViewO.getScaleX() * scaleFactor);
mapViewO.setScaleY(mapViewO.getScaleY() * scaleFactor);
SCALE_TOTAL *= scaleFactor;
double newCenterX = centerPosX * scaleFactor;
double newCenterY = centerPosY * scaleFactor;
mapScroll.setHvalue((newCenterX - viewPort.getWidth()/2) / (contentSize.getWidth() * scaleFactor - viewPort.getWidth()));
mapScroll.setVvalue((newCenterY - viewPort.getHeight()/2) / (contentSize.getHeight() * scaleFactor -viewPort.getHeight()));
}
所以我在 JavaFX 中创建了一个地图,我希望有时可以看到整个地图。但是,问题是,在我将 imageView 设置为适合屏幕尺寸然后将其添加到 scrollPane 之后,我的缩放功能工作正常,但是一旦我放大,我就不允许在图像周围平移。下面是我写的代码。
package gameaspects;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class SourceCodeVersion8 extends Application{
final double SCALE_DELTA = 1.1;
public double SCALE_TOTAL = 1;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
AnchorPane mapAnchorO = addMapAnchor();
Scene mapScene = new Scene(mapAnchorO);
primaryStage.setScene(mapScene);
primaryStage.setFullScreen(true);
primaryStage.setResizable(false);
primaryStage.show();
}
//Creates an AnchorPane for the map
private AnchorPane addMapAnchor()
{
AnchorPane mapAnchor = new AnchorPane();
ScrollPane mapScrollO = addMapScroll();
mapAnchor.getChildren().add(mapScrollO);
AnchorPane.setLeftAnchor(mapScrollO, 0.0);
AnchorPane.setTopAnchor(mapScrollO, 0.0);
AnchorPane.setBottomAnchor(mapScrollO, 0.0);
AnchorPane.setRightAnchor(mapScrollO, 0.0);
return mapAnchor;
}
//Creates an ImageView for the map
private ImageView addMapView()
{
Image mapImage = new Image("WorldProvincialMap-v1.01.png");
ImageView mapView = new ImageView(mapImage);
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
int width = gd.getDisplayMode().getWidth();
int height = gd.getDisplayMode().getHeight();
mapView.setFitHeight(height);
mapView.setFitWidth(width);
return mapView;
}
//Creates a scrollPane for the map
private ScrollPane addMapScroll()
{
ScrollPane mapScroll = new ScrollPane();
ImageView mapViewO = addMapView();
mapScroll.setContent(mapViewO);
mapScroll.setPannable(true);
mapScroll.setVbarPolicy(ScrollBarPolicy.NEVER);
mapScroll.setHbarPolicy(ScrollBarPolicy.NEVER);
mapScroll.addEventFilter(ScrollEvent.ANY, e ->{
e.consume();
if(e.getDeltaY() == 0)
{
return;
}
double scaleFactor =
(e.getDeltaY() > 0)
? SCALE_DELTA
: 1/SCALE_DELTA;
if(scaleFactor * SCALE_TOTAL >= 1)
{
mapScroll.setScaleX(mapScroll.getScaleX() * scaleFactor);
mapScroll.setScaleY(mapScroll.getScaleY() * scaleFactor);
SCALE_TOTAL *= scaleFactor;
}
});
return mapScroll;
}
}
我用 mouseDragHandler 改进了你的版本。
这应该是解决您问题的正确方法!
package test;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class test extends Application {
final double SCALE_DELTA = 1.1;
public double SCALE_TOTAL = 1;
public double dragDeltay;
public double dragDeltax;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
AnchorPane mapAnchorO = addMapAnchor();
Scene mapScene = new Scene(mapAnchorO);
primaryStage.setScene(mapScene);
primaryStage.setFullScreen(true);
primaryStage.setResizable(false);
primaryStage.show();
}
// Creates an AnchorPane for the map
private AnchorPane addMapAnchor() {
AnchorPane mapAnchor = new AnchorPane();
ScrollPane mapScrollO = addMapScroll();
mapAnchor.getChildren().add(mapScrollO);
AnchorPane.setLeftAnchor(mapScrollO, 0.0);
AnchorPane.setTopAnchor(mapScrollO, 0.0);
AnchorPane.setBottomAnchor(mapScrollO, 0.0);
AnchorPane.setRightAnchor(mapScrollO, 0.0);
return mapAnchor;
}
// Creates an ImageView for the map
private ImageView addMapView() {
Image mapImage = new Image("WorldProvincialMap-v1.01.png");
ImageView mapView = new ImageView(mapImage);
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
int width = gd.getDisplayMode().getWidth();
int height = gd.getDisplayMode().getHeight();
mapView.setFitHeight(height);
mapView.setFitWidth(width);
return mapView;
}
// Creates a scrollPane for the map
private ScrollPane addMapScroll() {
ScrollPane mapScroll = new ScrollPane();
ImageView mapViewO = addMapView();
mapScroll.setContent(mapViewO);
mapViewO.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
dragDeltax = mapViewO.getX() - mouseEvent.getScreenX();
dragDeltay = mapViewO.getY() - mouseEvent.getScreenY();
}
});
mapViewO.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
mapScroll.setTranslateX(mouseEvent.getScreenX() + dragDeltax);
mapScroll.setTranslateY(mouseEvent.getScreenY() + dragDeltay);
}
});
mapScroll.setVbarPolicy(ScrollBarPolicy.NEVER);
mapScroll.setHbarPolicy(ScrollBarPolicy.NEVER);
mapScroll.addEventFilter(ScrollEvent.ANY, e -> {
e.consume();
if (e.getDeltaY() == 0) {
return;
}
double scaleFactor = (e.getDeltaY() > 0) ? SCALE_DELTA : 1 / SCALE_DELTA;
if (scaleFactor * SCALE_TOTAL >= 1) {
mapScroll.setScaleX(mapScroll.getScaleX() * scaleFactor);
mapScroll.setScaleY(mapScroll.getScaleY() * scaleFactor);
SCALE_TOTAL *= scaleFactor;
}
});
return mapScroll;
}
}
您正在缩放 ScrollPane
而不是内容。此外,即使您缩放 ImageView
,scaleX
和 scaleY
在计算内容大小时也不会被考虑在内。因此 ImageView
也应该包裹在 Group
:
private ScrollPane addMapScroll() {
ScrollPane mapScroll = new ScrollPane();
ImageView mapViewO = addMapView();
mapScroll.setContent(new Group(mapViewO));
mapScroll.setPannable(true);
mapScroll.setVbarPolicy(ScrollBarPolicy.NEVER);
mapScroll.setHbarPolicy(ScrollBarPolicy.NEVER);
mapScroll.addEventFilter(ScrollEvent.ANY, e -> {
e.consume();
if (e.getDeltaY() == 0) {
return;
}
double scaleFactor
= (e.getDeltaY() > 0)
? SCALE_DELTA
: 1 / SCALE_DELTA;
if (scaleFactor * SCALE_TOTAL >= 1) {
mapViewO.setScaleX(mapViewO.getScaleX() * scaleFactor);
mapViewO.setScaleY(mapViewO.getScaleY() * scaleFactor);
SCALE_TOTAL *= scaleFactor;
}
});
return mapScroll;
}
要"keep the center centered",您需要相应地调整滚动位置:
if (scaleFactor * SCALE_TOTAL >= 1) {
Bounds viewPort = mapScroll.getViewportBounds();
Bounds contentSize = mapViewO.getBoundsInParent();
double centerPosX = (contentSize.getWidth() - viewPort.getWidth()) * mapScroll.getHvalue() + viewPort.getWidth() / 2;
double centerPosY = (contentSize.getHeight() - viewPort.getHeight()) * mapScroll.getVvalue() + viewPort.getHeight() / 2;
mapViewO.setScaleX(mapViewO.getScaleX() * scaleFactor);
mapViewO.setScaleY(mapViewO.getScaleY() * scaleFactor);
SCALE_TOTAL *= scaleFactor;
double newCenterX = centerPosX * scaleFactor;
double newCenterY = centerPosY * scaleFactor;
mapScroll.setHvalue((newCenterX - viewPort.getWidth()/2) / (contentSize.getWidth() * scaleFactor - viewPort.getWidth()));
mapScroll.setVvalue((newCenterY - viewPort.getHeight()/2) / (contentSize.getHeight() * scaleFactor -viewPort.getHeight()));
}