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 而不是内容。此外,即使您缩放 ImageViewscaleXscaleY 在计算内容大小时也不会被考虑在内。因此 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()));
}