Пользовательский обработчик панорамирования Javafx

Здравствуйте, из-за проблем со встроенным инструментом панорамирования для scrollpane (работает медленно и переходит порциями, а не плавно). Я пытаюсь создать собственный обработчик панорамирования. Ниже моя попытка, но оператор if работает неправильно.

    mapScroll.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> {
        startX = e.getX();
        startY = e.getY();
    });
    mapScroll.addEventFilter(MouseEvent.MOUSE_DRAGGED, e -> {
        endX = e.getX();
        endY = e.getY();
        Bounds viewBounds = mapScroll.getViewportBounds();
        Bounds mapBounds = mapScroll.getBoundsInParent();
        double xMin = viewBounds.getMinX();
        double xMax = viewBounds.getMaxX();
        double yMin = viewBounds.getMinY();
        double yMax = viewBounds.getMaxY();
        double startEndX = endX - startX;
        double startEndY = endY - startY;
        if(mapBounds.contains(xMin + startEndX, yMin + startEndY) && mapBounds.contains(xMin + startEndX, yMax + startEndY) && mapBounds.contains(xMax + startEndX, yMin + startEndY) && mapBounds.contains(xMax + startEndX, yMax + startEndY))
        {
            double fullWidth = mapScroll.getWidth();
            double fullHeight = mapScroll.getHeight();
            double hChange = startEndX/fullWidth;
            double vChange = startEndY/fullHeight;
            mapScroll.setHvalue(mapScroll.getHvalue() + hChange);
            mapScroll.setVvalue(mapScroll.getVvalue() + vChange);
        }
        endX = startX;
        endY = startY;
    });

person Politic Revolutionnaire    schedule 20.10.2016    source источник


Ответы (1)


Вы никогда не используете ширину содержимого в своих вычислениях. Это означает, что вам нужно перемещать мышь на одинаковое расстояние для прокрутки с одной стороны на другую и вниз, независимо от размера содержимого. Независимо от того, является ли содержимое всего на 10 пикселей больше, чем область просмотра, или содержимое в 10 раз больше размера области просмотра, не имеет значения для вашего кода. Кроме того, обратите внимание, что

endX = startX;
endY = startY;

абсолютно бесполезен, так как вы все равно перезаписываете значения в начале каждого вызова фильтра событий. Вероятно, вы хотели выполнить задания наоборот.

Также вы перемещаете положение прокрутки в том же направлении, что и движение мыши. Однако вам следует переместить положение прокрутки в противоположном направлении, если вы хотите, чтобы положение мыши оставалось неизменным относительно содержимого.

Вот пример (тесты границ удалены для простоты):

private double startX;
private double startY;

@Override
public void start(Stage primaryStage) {
    ImageView image = new ImageView("https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/687px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg");
    ScrollPane mapScroll = new ScrollPane(image);
    Scene scene = new Scene(mapScroll, 400, 400);
    mapScroll.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> {
        startX = e.getX();
        startY = e.getY();
    });
    mapScroll.addEventFilter(MouseEvent.MOUSE_DRAGGED, e -> {
        double endX = e.getX();
        double endY = e.getY();
        Bounds viewBounds = mapScroll.getViewportBounds();

        double startEndX = startX - endX;
        double startEndY = startY - endY;

        Bounds contentBounds = mapScroll.getContent().getLayoutBounds();

        double hChange = startEndX / (contentBounds.getWidth() - viewBounds.getWidth());
        double vChange = startEndY / (contentBounds.getHeight() - viewBounds.getHeight());
        mapScroll.setHvalue(mapScroll.getHvalue() + hChange);
        mapScroll.setVvalue(mapScroll.getVvalue() + vChange);

        startX = endX;
        startY = endY;
    });

    primaryStage.setScene(scene);
    primaryStage.show();
}
person fabian    schedule 20.10.2016